├── .gitignore ├── Makefile ├── ast_rvas ├── Makefile ├── rvas_lib │ ├── Makefile │ ├── rvas.c │ ├── rvas.h │ └── video_ioctl.h ├── rvas_test.c └── vtest.c ├── espi_test ├── Makefile ├── aspeed-espi.h └── oob-pch-test.c ├── i2c-slave-mqueue ├── Makefile └── i2c-slave-mqueue.c ├── i2c-test ├── Makefile └── i2c-test.c ├── i3c-test ├── Makefile ├── i3c-test.c └── i3c-test.o ├── mctp-i3c ├── Makefile └── mctp-i3c.c ├── mctp-socket ├── mctp-recv.c ├── mctp-req.c ├── mctp-util.c ├── mctp-util.h ├── mctp.h └── meson.build ├── mctp ├── Makefile ├── libmctp.c ├── libmctp.h ├── list.h └── mctp.c ├── mem_utils ├── Makefile ├── compiler.h ├── md.c ├── mem_common.c ├── mem_common.h └── mw.c ├── meson.build ├── otp ├── Makefile ├── aspeed-otp.h ├── lib_otp_ast2700.c ├── otp_ast2600.c ├── otp_ast2600.h ├── otp_ast2700.c ├── otp_ast2700.h ├── otp_info_ast2600.h ├── otp_info_ast2700.h ├── otp_prov.c └── utils.h ├── svf ├── LCMXO2-7000HE │ ├── erase.svf │ ├── mxo2.svf │ └── program.svf ├── Makefile ├── ast-jtag.c ├── ast-jtag.h ├── jtag.h ├── main.c ├── svf.c └── svf.h ├── usb ├── Makefile └── hid_gadget_test.c └── video ├── Makefile ├── bmp.cc ├── bmp.h ├── ikvm_video.cpp ├── ikvm_video.hpp ├── main.cc ├── main1.cc ├── main2.cc ├── regs-video.h ├── video.cc ├── video.h └── video.inf /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0-only 2 | # 3 | # Copyright 2021 Aspeed Technology Inc. 4 | # 5 | 6 | all: 7 | for dir in */ ; do \ 8 | if [ -d "$$dir" ] && [ -f "$$dir/Makefile" ]; then \ 9 | make -C "$$dir" || exit 1; \ 10 | fi; \ 11 | done 12 | 13 | clean: 14 | find . -maxdepth 1 -type d \( ! -name . \) -exec make -C {} clean \; 15 | 16 | install: 17 | find . -maxdepth 1 -type d \( ! -name . \) -exec make -C {} install \; 18 | -------------------------------------------------------------------------------- /ast_rvas/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright 2021 Aspeed Technology Inc. 4 | 5 | ifdef INST 6 | ifeq ("$(origin INST)", "command line") 7 | INSTALL_DIR := $(INST) 8 | endif 9 | endif 10 | 11 | CC=$(CROSS_COMPILE)gcc 12 | RVAS_DRIVER_DIR=$(AST_SDK_TOP)/kernel/linux/drivers/soc/aspeed/rvas/ 13 | 14 | VTEST_OBJS := vtest.o 15 | RVAS_TEST_OBJS := rvas_test.o 16 | 17 | VTEST_DEPS=$(VTEST_OBJS:.o=.d) 18 | RVAS_TEST_DEPS=$(RVAS_TEST_OBJS:.o=.d) 19 | 20 | VTEST_NAME=vtest 21 | RVAS_TEST_NAME=rvas_test 22 | RM=rm 23 | SED=sed 24 | LIB_RVAS=./rvas_lib/librvas.a 25 | APP_MAKEFILE=Makefile 26 | 27 | LD_FLAGS= 28 | #CFLAGS+=-c -g -DDEBUG -Wall -Wstrict-prototypes -I./rvas_lib/ -I./include/ 29 | CFLAGS+=-c -g -Wall -Wstrict-prototypes -I./rvas_lib/ -I$(RVAS_DRIVER_DIR) 30 | RM_FLAGS=-f 31 | DEP_FLAGS=-MM 32 | LDFLAGS= 33 | LIBS=-lrt -lpthread $(LIB_RVAS) 34 | 35 | all: ${VTEST_NAME} ${RVAS_TEST_NAME} 36 | 37 | %.o: %.c 38 | $(CC) $(CFLAGS) $*.c -o $*.o 39 | @set -e; $(RM) $(RM_FLAGS) $*.d; \ 40 | $(CC) $(DEP_FLAGS) $(CFLAGS) $< > $*.d.tmp; \ 41 | $(SED) 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $*.d.tmp > $*.d; \ 42 | $(RM) $(RM_FLAGS) $*.d.tmp 43 | 44 | -include $(VTEST_DEPS) 45 | -include $(RVAS_TEST_DEPS) 46 | 47 | $(LIB_RVAS): 48 | $(MAKE) -C ./rvas_lib 49 | 50 | ${VTEST_NAME}: $(VTEST_OBJS) $(LIB_RVAS) 51 | $(CC) $(LD_FLAGS) $^ $(LIBS) -o $@ 52 | 53 | ${RVAS_TEST_NAME}: $(RVAS_TEST_OBJS) $(LIB_RVAS) 54 | $(CC) $(LD_FLAGS) $^ $(LIBS) -o $@ 55 | 56 | .PHONY: clean 57 | clean: 58 | $(RM) $(RM_FLAGS) ${VTEST_NAME} $(VTEST_OBJS) $(VTEST_DEPS) ${RVAS_TEST_NAME} $(RVAS_TEST_OBJS) $(RVAS_TEST_DEPS) 59 | $(MAKE) -C ./rvas_lib clean 60 | 61 | .PHONY: rebuild 62 | rebuild: clean all 63 | 64 | .PHONY: install 65 | install: all 66 | cp $(VTEST_NAME) $(INSTALL_DIR) 67 | cp $(RVAS_TEST_NAME) $(INSTALL_DIR) 68 | -------------------------------------------------------------------------------- /ast_rvas/rvas_lib/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright 2021 Aspeed Technology Inc. 4 | 5 | CC=$(CROSS_COMPILE)gcc 6 | AR=$(CROSS_COMPILE)ar 7 | 8 | CFLAGS += -I$(AST_SDK_TOP)/kernel/linux/drivers/soc/aspeed/rvas/ 9 | 10 | 11 | LIB_NAME=librvas.a 12 | LIB_OBJS=rvas.o 13 | LIB_DEPS=$(LIB_OBJS:.o=.d) 14 | LIB_MAKEFILE=Makefile 15 | 16 | RM=rm 17 | SED=sed 18 | 19 | #CFLAGS+=-c -g -DDEBUG -Wall -Wstrict-prototypes 20 | #CFLAGS+=-c -g -Wall -Wstrict-prototypes 21 | CFLAGS+=-c -O3 -Wall -Wstrict-prototypes 22 | AR_FLAGS=-rcs 23 | RM_FLAGS=-f 24 | DEP_FLAGS=-MM 25 | 26 | all: $(LIB_NAME) 27 | 28 | %.o: %.c 29 | $(CC) $(CFLAGS) $*.c -o $*.o 30 | @set -e; $(RM) $(RM_FLAGS) $*.d; \ 31 | $(CC) $(DEP_FLAGS) $(CFLAGS) $< > $*.d.tmp; \ 32 | $(SED) 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $*.d.tmp > $*.d; \ 33 | $(RM) $(RM_FLAGS) $*.d.tmp 34 | 35 | -include $(LIB_DEPS) 36 | 37 | $(LIB_NAME): $(LIB_OBJS) 38 | $(AR) $(AR_FLAGS) $@ $^ 39 | 40 | .PHONY: clean 41 | clean: 42 | -$(RM) $(RM_FLAGS) $(LIB_NAME) $(LIB_OBJS) $(LIB_DEPS) 43 | 44 | .PHONY: rebuild 45 | rebuild: clean all 46 | -------------------------------------------------------------------------------- /ast_rvas/rvas_lib/rvas.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright 2021 Aspeed Technology Inc. 4 | */ 5 | 6 | 7 | #ifndef __RVAS_API_H_ 8 | #define __RVAS_API_H_ 9 | 10 | typedef unsigned char u8; 11 | typedef unsigned short u16; 12 | typedef unsigned int u32; 13 | typedef unsigned long long u64; 14 | 15 | #include "video_ioctl.h" 16 | 17 | #define DEBUG (0) 18 | //#define USE_FILE_LOG 19 | 20 | #undef min 21 | #define min(x, y) ((x) < (y) ? (x) : (y)) 22 | 23 | int OpenLog(const char *name); 24 | void CloseLog(void); 25 | #ifdef USE_FILE_LOG 26 | void Log(const char*, ...); 27 | void LogInfo(const char*, ...); 28 | #else 29 | #define Log(fmt, args...) do { if (DEBUG) { printf("Client: %s: " fmt, __FUNCTION__, ## args); } } while (0) 30 | #define LogInfo(fmt, args...) do { if (DEBUG) { printf(fmt, ## args); } } while (0) 31 | #endif // USE_FILE_LOG 32 | void DisplayBuffer(void*, u32); 33 | 34 | enum RVASStatus Initialize(void); 35 | enum RVASStatus Shutdown(void); 36 | enum RVASStatus NewContext(void **aNewContextPtr); 37 | enum RVASStatus DeleteContext(void *aContext); 38 | enum RVASStatus Alloc(size_t aLengthInBytes, void **aBufferPtr, void **aMemoryHandlePtr); 39 | // in:rvb, out:rmh 40 | enum RVASStatus Free(void *aMemoryHandle); // in:rmh, out:rvb 41 | 42 | enum RVASStatus LocalMonitorOn(void); 43 | enum RVASStatus LocalMonitorOff(void); 44 | enum RVASStatus IsLocalMonitorOn(bool *pbMonitorIsOn); 45 | 46 | enum RVASStatus GetVideoGeometry(struct VideoGeometry *aGeometryPtr); // out:vg 47 | void display_event_map(const struct EventMap *pem); 48 | enum RVASStatus WaitForVideoEvent(void *aContext, struct EventMap anEventMap, 49 | struct EventMap *aMapPtr, u32 aTimeoutInMs); // in:rc, em, dw, out:em, 50 | enum RVASStatus GetGRCRegisters(void *aMemoryHandle); // in:rc, gm, out:rmh 51 | enum RVASStatus ReadSnoopMap(void *aContext, void *aMemoryHandle, bool bClear); 52 | enum RVASStatus ReadSnoopAggregate(void *aContext, struct SnoopAggregate *anAggregatePtr, 53 | bool bClear); // in:rc, b, out:sa 54 | 55 | enum RVASStatus FetchVideoTiles(void *rc, void *aMemoryHandleFVTA, 56 | void *aMemoryHandleOutput, 57 | void *aMemoryHandleTemp); 58 | // This aMemoryHandleTemp buffer need to be the same size as output buffer 59 | 60 | // in:rmh(descriptors), rmh2(video data out), out:dw(checksum), dw2(rle count) 61 | enum RVASStatus FetchVideoSlices(void *rc, void *aMemoryHandleFSA, 62 | void *aMemoryHandleNonRLE, void *aMemoryHandleRLE); 63 | 64 | enum RVASStatus FetchTextData(void *rc, struct VideoGeometry aGeometry, 65 | struct FetchMap *paTextMap, void *aMemoryHandleNonRLE, 66 | void *aMemoryHandleRLE); // in:vg, tfm, rmh, out:dw 67 | 68 | //mode 13 69 | enum RVASStatus FetchVGAGraphicsData(void *rc, struct VideoGeometry aGeometry, 70 | struct FetchMap *paVideoMap, 71 | void *aMemoryHandleNonRLE, void *aMemoryHandleRLE); // in:vg, tfm, rmh, out:dw 72 | 73 | // in:rmh(descriptors), rmh2(video data out), out:dw(checksum), dw2(rle count) 74 | enum RVASStatus RunLengthEncode(void *aMemoryHandleIn, 75 | void *aMemoryHandleOut, u8 byRLETripletCode, 76 | u8 byRLERepeatCode, u32 *aRLECountPtr, u32 *aCheckSumPtr); //out:dw 77 | 78 | // Set Tile Snoop Interrupt Count Register (TSICR) 79 | enum RVASStatus SetTSECounter(u32 value); //out:dw 80 | 81 | // Get Tile Snoop Interrupt Count Register (TSICR) 82 | u32 GetTSECounter(void); //out:dw 83 | 84 | // Reset the Video Engine 85 | enum RVASStatus ResetVideoEngine(enum ResetEngineMode resetMode); //out:dw 86 | 87 | // Get the Video Engine Config 88 | enum RVASStatus GetVideoEngineConfig(struct VideoConfig *ast_config); //out:dw 89 | 90 | // Set the Video Engine Config 91 | enum RVASStatus SetVideoEngineConfig(const struct VideoConfig *ast_config); //out:dw 92 | 93 | // Get the Video Engine Data 94 | enum RVASStatus GetVideoEngineJPEGData(struct MultiJpegConfig *ast_multi); 95 | //void*aMemoryHandle); //out:dw 96 | 97 | #endif //__RVAS_API_H_ 98 | -------------------------------------------------------------------------------- /ast_rvas/rvas_lib/video_ioctl.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ */ 2 | /* 3 | * Copyright 2021 Aspeed Technology Inc. 4 | */ 5 | 6 | #ifndef _VIDEO_IOCTL_H 7 | #define _VIDEO_IOCTL_H 8 | 9 | #include 10 | 11 | #define RVAS_MAGIC ('b') 12 | #define CMD_IOCTL_TURN_LOCAL_MONITOR_ON _IOR(RVAS_MAGIC, \ 13 | IOCTL_TURN_LOCAL_MONITOR_ON, struct RvasIoctl) 14 | #define CMD_IOCTL_TURN_LOCAL_MONITOR_OFF _IOR(RVAS_MAGIC, \ 15 | IOCTL_TURN_LOCAL_MONITOR_OFF, struct RvasIoctl) 16 | #define CMD_IOCTL_IS_LOCAL_MONITOR_ENABLED _IOR(RVAS_MAGIC, \ 17 | IOCTL_IS_LOCAL_MONITOR_ENABLED, struct RvasIoctl) 18 | #define CMD_IOCTL_GET_VIDEO_GEOMETRY _IOWR(RVAS_MAGIC, \ 19 | IOCTL_GET_VIDEO_GEOMETRY, struct RvasIoctl) 20 | #define CMD_IOCTL_WAIT_FOR_VIDEO_EVENT _IOWR(RVAS_MAGIC, \ 21 | IOCTL_WAIT_FOR_VIDEO_EVENT, struct RvasIoctl) 22 | #define CMD_IOCTL_GET_GRC_REGIESTERS _IOWR(RVAS_MAGIC, \ 23 | IOCTL_GET_GRC_REGIESTERS, struct RvasIoctl) 24 | #define CMD_IOCTL_READ_SNOOP_MAP _IOWR(RVAS_MAGIC, \ 25 | IOCTL_READ_SNOOP_MAP, struct RvasIoctl) 26 | #define CMD_IOCTL_READ_SNOOP_AGGREGATE _IOWR(RVAS_MAGIC, \ 27 | IOCTL_READ_SNOOP_AGGREGATE, struct RvasIoctl) 28 | #define CMD_IOCTL_FETCH_VIDEO_TILES _IOWR(RVAS_MAGIC, \ 29 | IOCTL_FETCH_VIDEO_TILES, struct RvasIoctl) 30 | #define CMD_IOCTL_FETCH_VIDEO_SLICES _IOWR(RVAS_MAGIC, \ 31 | IOCTL_FETCH_VIDEO_SLICES, struct RvasIoctl) 32 | #define CMD_IOCTL_RUN_LENGTH_ENCODE_DATA _IOWR(RVAS_MAGIC, \ 33 | IOCTL_RUN_LENGTH_ENCODE_DATA, struct RvasIoctl) 34 | #define CMD_IOCTL_FETCH_TEXT_DATA _IOWR(RVAS_MAGIC, \ 35 | IOCTL_FETCH_TEXT_DATA, struct RvasIoctl) 36 | #define CMD_IOCTL_FETCH_MODE13_DATA _IOWR(RVAS_MAGIC, \ 37 | IOCTL_FETCH_MODE13_DATA, struct RvasIoctl) 38 | #define CMD_IOCTL_NEW_CONTEXT _IOWR(RVAS_MAGIC, \ 39 | IOCTL_NEW_CONTEXT, struct RvasIoctl) 40 | #define CMD_IOCTL_DEL_CONTEXT _IOWR(RVAS_MAGIC, \ 41 | IOCTL_DEL_CONTEXT, struct RvasIoctl) 42 | #define CMD_IOCTL_ALLOC _IOWR(RVAS_MAGIC, \ 43 | IOCTL_ALLOC, struct RvasIoctl) 44 | #define CMD_IOCTL_FREE _IOWR(RVAS_MAGIC, \ 45 | IOCTL_FREE, struct RvasIoctl) 46 | #define CMD_IOCTL_SET_TSE_COUNTER _IOWR(RVAS_MAGIC, \ 47 | IOCTL_SET_TSE_COUNTER, struct RvasIoctl) 48 | #define CMD_IOCTL_GET_TSE_COUNTER _IOWR(RVAS_MAGIC, \ 49 | IOCTL_GET_TSE_COUNTER, struct RvasIoctl) 50 | #define CMD_IOCTL_VIDEO_ENGINE_RESET _IOWR(RVAS_MAGIC, \ 51 | IOCTL_VIDEO_ENGINE_RESET, struct RvasIoctl) 52 | //jpeg 53 | #define CMD_IOCTL_SET_VIDEO_ENGINE_CONFIG _IOW(RVAS_MAGIC, \ 54 | IOCTL_SET_VIDEO_ENGINE_CONFIG, struct VideoConfig*) 55 | #define CMD_IOCTL_GET_VIDEO_ENGINE_CONFIG _IOW(RVAS_MAGIC, \ 56 | IOCTL_GET_VIDEO_ENGINE_CONFIG, struct VideoConfig*) 57 | #define CMD_IOCTL_GET_VIDEO_ENGINE_DATA _IOWR(RVAS_MAGIC, \ 58 | IOCTL_GET_VIDEO_ENGINE_DATA, struct MultiJpegConfig*) 59 | 60 | enum HARD_WARE_ENGINE_IOCTL { 61 | IOCTL_TURN_LOCAL_MONITOR_ON = 20, //REMOTE VIDEO GENERAL IOCTL 62 | IOCTL_TURN_LOCAL_MONITOR_OFF, 63 | IOCTL_IS_LOCAL_MONITOR_ENABLED, 64 | 65 | IOCTL_GET_VIDEO_GEOMETRY = 40, // REMOTE VIDEO 66 | IOCTL_WAIT_FOR_VIDEO_EVENT, 67 | IOCTL_GET_GRC_REGIESTERS, 68 | IOCTL_READ_SNOOP_MAP, 69 | IOCTL_READ_SNOOP_AGGREGATE, 70 | IOCTL_FETCH_VIDEO_TILES, 71 | IOCTL_FETCH_VIDEO_SLICES, 72 | IOCTL_RUN_LENGTH_ENCODE_DATA, 73 | IOCTL_FETCH_TEXT_DATA, 74 | IOCTL_FETCH_MODE13_DATA, 75 | IOCTL_NEW_CONTEXT, 76 | IOCTL_DEL_CONTEXT, 77 | IOCTL_ALLOC, 78 | IOCTL_FREE, 79 | IOCTL_SET_TSE_COUNTER, 80 | IOCTL_GET_TSE_COUNTER, 81 | IOCTL_VIDEO_ENGINE_RESET, 82 | IOCTL_SET_VIDEO_ENGINE_CONFIG, 83 | IOCTL_GET_VIDEO_ENGINE_CONFIG, 84 | IOCTL_GET_VIDEO_ENGINE_DATA, 85 | }; 86 | 87 | enum GraphicsModeType { 88 | InvalidMode = 0, TextMode = 1, VGAGraphicsMode = 2, AGAGraphicsMode = 3 89 | }; 90 | 91 | enum RVASStatus { 92 | SuccessStatus = 0, 93 | GenericError = 1, 94 | MemoryAllocError = 2, 95 | InvalidMemoryHandle = 3, 96 | CannotMapMemory = 4, 97 | CannotUnMapMemory = 5, 98 | TimedOut = 6, 99 | InvalidContextHandle = 7, 100 | CaptureTimedOut = 8, 101 | CompressionTimedOut = 9, 102 | HostSuspended 103 | }; 104 | 105 | enum SelectedByteMode { 106 | AllBytesMode = 0, 107 | SkipMode = 1, 108 | PlanarToPackedMode, 109 | PackedToPackedMode, 110 | LowByteMode, 111 | MiddleByteMode, 112 | TopByteMode 113 | }; 114 | 115 | enum DataProccessMode { 116 | NormalTileMode = 0, 117 | FourBitPlanarMode = 1, 118 | FourBitPackedMode = 2, 119 | AttrMode = 3, 120 | AsciiOnlyMode = 4, 121 | FontFetchMode = 5, 122 | SplitByteMode = 6 123 | }; 124 | 125 | enum ResetEngineMode { 126 | ResetAll = 0, 127 | ResetRvasEngine = 1, 128 | ResetVeEngine = 2 129 | }; 130 | 131 | struct VideoGeometry { 132 | u16 wScreenWidth; 133 | u16 wScreenHeight; 134 | u16 wStride; 135 | u8 byBitsPerPixel; 136 | u8 byModeID; 137 | enum GraphicsModeType gmt; 138 | }; 139 | 140 | struct EventMap { 141 | u32 bPaletteChanged :1; 142 | u32 bATTRChanged :1; 143 | u32 bSEQChanged :1; 144 | u32 bGCTLChanged :1; 145 | u32 bCRTCChanged :1; 146 | u32 bCRTCEXTChanged :1; 147 | u32 bPLTRAMChanged :1; 148 | u32 bXCURCOLChanged :1; 149 | u32 bXCURCTLChanged :1; 150 | u32 bXCURPOSChanged :1; 151 | u32 bDoorbellA :1; 152 | u32 bDoorbellB :1; 153 | u32 bGeometryChanged :1; 154 | u32 bSnoopChanged :1; 155 | u32 bTextFontChanged :1; 156 | u32 bTextATTRChanged :1; 157 | u32 bTextASCIIChanged :1; 158 | }; 159 | 160 | struct FetchMap { 161 | //in parameters 162 | bool bEnableRLE; 163 | u8 bTextAlignDouble; // 0 - 8 byte, 1 - 16 byte 164 | u8 byRLETripletCode; 165 | u8 byRLERepeatCode; 166 | enum DataProccessMode dpm; 167 | //out parameters 168 | u32 dwFetchSize; 169 | u32 dwFetchRLESize; 170 | u32 dwCheckSum; 171 | bool bRLEFailed; 172 | u8 rsvd[3]; 173 | }; 174 | 175 | struct SnoopAggregate { 176 | u64 qwRow; 177 | u64 qwCol; 178 | }; 179 | 180 | struct FetchRegion { 181 | u16 wTopY; 182 | u16 wLeftX; 183 | u16 wBottomY; 184 | u16 wRightX; 185 | }; 186 | 187 | struct FetchOperation { 188 | struct FetchRegion fr; 189 | enum SelectedByteMode sbm; 190 | u32 dwFetchSize; 191 | u32 dwFetchRLESize; 192 | u32 dwCheckSum; 193 | bool bRLEFailed; 194 | bool bEnableRLE; 195 | u8 byRLETripletCode; 196 | u8 byRLERepeatCode; 197 | u8 byVGATextAlignment; //0-8bytes, 1-16bytes. 198 | }; 199 | 200 | struct FetchVideoTilesArg { 201 | struct VideoGeometry vg; 202 | u32 dwTotalOutputSize; 203 | u32 cfo; 204 | struct FetchOperation pfo[4]; 205 | }; 206 | 207 | struct FetchVideoSlicesArg { 208 | struct VideoGeometry vg; 209 | u32 dwSlicedSize; 210 | u32 dwSlicedRLESize; 211 | u32 dwCheckSum; 212 | bool bEnableRLE; 213 | bool bRLEFailed; 214 | u8 byRLETripletCode; 215 | u8 byRLERepeatCode; 216 | u8 cBuckets; 217 | u8 abyBitIndexes[24]; 218 | u32 cfr; 219 | struct FetchRegion pfr[4]; 220 | }; 221 | 222 | struct RVASBuffer { 223 | void *pv; 224 | size_t cb; 225 | }; 226 | 227 | 228 | struct RvasIoctl { 229 | enum RVASStatus rs; 230 | void *rc; 231 | struct RVASBuffer rvb; 232 | void *rmh; 233 | void *rmh1; 234 | void *rmh2; 235 | u32 rmh_mem_size; 236 | u32 rmh1_mem_size; 237 | u32 rmh2_mem_size; 238 | struct VideoGeometry vg; 239 | struct EventMap em; 240 | struct SnoopAggregate sa; 241 | union { 242 | u32 tse_counter; 243 | u32 req_mem_size; 244 | u32 encode; 245 | u32 time_out; 246 | }; 247 | u32 rle_len; // RLE Length 248 | u32 rle_checksum; 249 | struct FetchMap tfm; 250 | u8 flag; 251 | u8 lms; 252 | u8 resetMode; 253 | u8 rsvd[1]; 254 | }; 255 | 256 | 257 | // 258 | // Video Engine 259 | // 260 | 261 | #define MAX_MULTI_FRAME_CT (32) 262 | 263 | struct VideoConfig { 264 | u8 engine; //0: engine 0 - normal engine, engine 1 - VM legacy engine 265 | u8 compression_mode; //0:DCT, 1:DCT_VQ mix VQ-2 color, 2:DCT_VQ mix VQ-4 color 9: 266 | u8 compression_format; //0:ASPEED 1:JPEG 267 | u8 capture_format; //0:CCIR601-2 YUV, 1:JPEG YUV, 2:RGB for ASPEED mode only, 3:Gray 268 | u8 rc4_enable; //0:disable 1:enable 269 | u8 YUV420_mode; //0:YUV444, 1:YUV420 270 | u8 Visual_Lossless; 271 | u8 Y_JPEGTableSelector; 272 | u8 AdvanceTableSelector; 273 | u8 AutoMode; 274 | u8 rsvd[2]; 275 | enum RVASStatus rs; 276 | }; 277 | 278 | struct MultiJpegFrame { 279 | u32 dwSizeInBytes; // Image size in bytes 280 | u32 dwOffsetInBytes; // Offset in bytes 281 | u16 wXPixels; // In: X coordinate 282 | u16 wYPixels; // In: Y coordinate 283 | u16 wWidthPixels; // In: Width for Fetch 284 | u16 wHeightPixels; // In: Height for Fetch 285 | }; 286 | 287 | struct MultiJpegConfig { 288 | unsigned char multi_jpeg_frames; // frame count 289 | struct MultiJpegFrame frame[MAX_MULTI_FRAME_CT]; // The Multi Frames 290 | void *aStreamHandle; 291 | enum RVASStatus rs; 292 | }; 293 | 294 | #endif // _VIDEO_IOCTL_H 295 | -------------------------------------------------------------------------------- /ast_rvas/rvas_test.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright 2021 Aspeed Technology Inc. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "rvas.h" 17 | 18 | static const char Copyright[] = "Copyright (c) 2010-2027 ASPEED Technology. All rights reserved."; 19 | 20 | //#define TEST_MONITOR_STATUS 21 | //#define TEST_WAIT_FOR_VIDEO_EVENT 22 | #define TEST_SNOOP 23 | //#define TEST_TSE_COUNTER 24 | 25 | typedef enum tagTestState { 26 | TS_SNOOPMAP_NO_CLEAR = 0, 27 | TS_SNOOPMAP_CLEAR = 1, 28 | TS_SNOOP_AGGREGATE_NO_CLEAR = 2, 29 | TS_SNOOP_AGGREGATE_CLEAR = 3, 30 | TS_MEMORY = 4, 31 | TS_RESET = 5, 32 | TS_TERMINATE = 6, 33 | } TestState; 34 | 35 | #define TIME_LIMIT_IN_SECS (10) 36 | #define BILLION (1000000000) 37 | 38 | const char szLogFile[] = ""; 39 | 40 | void time_diff(const struct timespec *start, const struct timespec *end, 41 | struct timespec *res) 42 | { 43 | if ((end->tv_nsec - start->tv_nsec) < 0) { 44 | res->tv_sec = end->tv_sec - start->tv_sec - 1; 45 | res->tv_nsec = BILLION + end->tv_nsec - start->tv_nsec; 46 | } else { 47 | res->tv_sec = end->tv_sec - start->tv_sec; 48 | res->tv_nsec = end->tv_nsec - start->tv_nsec; 49 | } 50 | } 51 | 52 | int main(int argc, char **argv) 53 | { 54 | u64 *pqw_snoop_map = NULL; 55 | u32 dw_iter; 56 | enum RVASStatus rs; 57 | void *rc; 58 | void *pv_buf = NULL; 59 | void *pv_buf_mem; 60 | void *rmh; 61 | void *rmh_mem; 62 | struct SnoopAggregate sa; 63 | u32 dw_allocate_sz; 64 | u32 dw_set_val; 65 | u32 dw_mem_disp_sz; 66 | u32 dw_sz = 0x500000; 67 | TestState ts_state; 68 | bool b_clear; 69 | #if defined(TEST_MONITOR_STATUS) || defined(TEST_WAIT_FOR_VIDEO_EVENT) 70 | int command = 0; 71 | #endif 72 | 73 | // Testing Wait For Video Event 74 | #ifdef TEST_TSE_COUNTER 75 | u32 dw_frame_ct; 76 | u32 dw_tse_counter; 77 | float f_avg_frames; 78 | u32 time_to_run_secs = TIME_LIMIT_IN_SECS; 79 | struct EventMap anEm; 80 | struct EventMap receivedEM; 81 | u32 dwTimeoutInMs = 1000; 82 | struct timespec start_time; 83 | struct timespec end_time; 84 | struct timespec res_time; 85 | #endif 86 | #ifdef TEST_WAIT_FOR_VIDEO_EVENT 87 | u32 dwMask = 0; 88 | #endif 89 | // Testing Wait For Video Event 90 | 91 | printf("%s\n", Copyright); 92 | Log("Opening log...\n"); 93 | if (!OpenLog(szLogFile)) { 94 | printf("Failed to start logging\n"); 95 | return EXIT_FAILURE; 96 | } 97 | 98 | Log("Start of RVAS test\n"); 99 | rs = Initialize(); 100 | Log("After Initialize\n"); 101 | 102 | if (rs != SuccessStatus) { 103 | Log("Initialized RVAS failed: %d\n", rs); 104 | return EXIT_FAILURE; 105 | } 106 | 107 | Log("Initialized RVAS session\n"); 108 | rs = NewContext(&rc); 109 | 110 | if (rs != SuccessStatus) { 111 | Log("Getting new context failed: %d\n", rs); 112 | return EXIT_FAILURE; 113 | } 114 | 115 | Log("Got RVAS context. rc: 0x%8.8x\n", (u32) rc); 116 | rs = Alloc(dw_sz, &pv_buf, &rmh); 117 | 118 | if (rs != SuccessStatus) { 119 | Log("Allocating memory failed: %d\n", rs); 120 | return EXIT_FAILURE; 121 | } 122 | #ifdef TEST_SNOOP 123 | pqw_snoop_map = (u64 *) pv_buf; 124 | Log("Got Memory handle. rmh: 0x%8.8x pqw_snoop_map: 0x%8.8x\n", (u32) rmh, 125 | (u32) pqw_snoop_map); 126 | 127 | do { 128 | Log("\nTest Options:\n"); 129 | Log(" 0 - SnoopMap (no clear) 1 - SnoopMap (clear)\n"); 130 | Log(" 2 - SnoopAggregate (no clear) 3 - SnoopAggregate (clear)\n"); 131 | Log(" 4 - Memory 5 - Reset RVAS Driver\n"); 132 | Log(" - Quit\n"); 133 | scanf("%d", (int *) &ts_state); 134 | 135 | switch (ts_state) { 136 | case TS_SNOOPMAP_NO_CLEAR: 137 | case TS_SNOOPMAP_CLEAR: 138 | b_clear = ts_state == TS_SNOOPMAP_CLEAR; 139 | 140 | if (b_clear) 141 | Log("Clear SnoopMap: true\n"); 142 | else 143 | Log("Clear SnoopMap: false\n"); 144 | 145 | rs = ReadSnoopMap(rc, rmh, b_clear); 146 | 147 | if (rs != SuccessStatus) { 148 | Log("Reading SnoopMap failed: %d\n", rs); 149 | return EXIT_FAILURE; 150 | } 151 | 152 | for (dw_iter = 0; dw_iter < 64; ++dw_iter) { 153 | Log("SnoopMap[%u]: 0x%16.16llx\n", dw_iter, 154 | pqw_snoop_map[dw_iter]); 155 | } 156 | break; 157 | 158 | case TS_SNOOP_AGGREGATE_NO_CLEAR: 159 | case TS_SNOOP_AGGREGATE_CLEAR: 160 | b_clear = ts_state == TS_SNOOP_AGGREGATE_CLEAR; 161 | 162 | if (b_clear) 163 | Log("Clear SnoopAggregate: true\n"); 164 | else 165 | Log("Clear SnoopAggregate: false\n"); 166 | 167 | 168 | rs = ReadSnoopAggregate(rc, &sa, b_clear); 169 | 170 | if (rs != SuccessStatus) { 171 | Log("Reading SnoopAggregate failed: %d\n", rs); 172 | return EXIT_FAILURE; 173 | } 174 | 175 | Log("SnoopAggregate rows: 0x%16.16llx\n", sa.qwRow); 176 | Log("SnoopAggregate cols: 0x%16.16llx\n", sa.qwCol); 177 | break; 178 | 179 | case TS_MEMORY: 180 | pv_buf_mem = NULL; 181 | Log("Enter number of bytes to allocate\n"); 182 | Log("Enter value to set\n"); 183 | Log("[Bytes] [Set]\n"); 184 | scanf("%u %u", &dw_allocate_sz, &dw_set_val); 185 | dw_set_val &= 0xff; 186 | dw_mem_disp_sz = dw_allocate_sz < 16 ? dw_allocate_sz : 16; 187 | Log("Allocating %u bytes with set value: %u (0x%2.2x)\n", 188 | dw_allocate_sz, dw_set_val, dw_set_val); 189 | rs = Alloc(dw_allocate_sz, &pv_buf_mem, &rmh_mem); 190 | 191 | if (rs != SuccessStatus) { 192 | Log("Allocating memory failed: %d\n", rs); 193 | return EXIT_FAILURE; 194 | } 195 | 196 | Log("Got Memory handle. rmh_mem: 0x%8.8x pv_buf_mem: 0x%8.8x\n", 197 | (u32) rmh_mem, (u32) pv_buf_mem); 198 | Log("\nMemory Before:\n"); 199 | DisplayBuffer(pv_buf_mem, dw_mem_disp_sz); 200 | memset(pv_buf_mem, dw_set_val, dw_allocate_sz); 201 | Log("\nMemory After:\n"); 202 | DisplayBuffer(pv_buf_mem, dw_mem_disp_sz); 203 | rs = Free(rmh_mem); 204 | 205 | if (rs != SuccessStatus) { 206 | Log("Freeing memory failed: %d\n", rs); 207 | return EXIT_FAILURE; 208 | } 209 | break; 210 | case TS_RESET: 211 | Log("Resetting RVAS Driver...\n"); 212 | ResetVideoEngine(ResetRvasEngine); 213 | Log("Reset complete for RVAS Driver\n"); 214 | break; 215 | default: 216 | ts_state = TS_TERMINATE; 217 | break; 218 | } 219 | } while (ts_state != TS_TERMINATE); 220 | #endif 221 | #if 1 222 | rs = Free(rmh); 223 | 224 | if (rs != SuccessStatus) { 225 | Log("Freeing memory failed: %d\n", rs); 226 | return EXIT_FAILURE; 227 | } 228 | #endif 229 | Log("Freed the Memory handle.\n"); 230 | 231 | #ifdef TEST_MONITOR_STATUS 232 | printf("Test monitor on/off\n"); 233 | 234 | while (command < 3) { 235 | printf("Enter 0-off, 1-on, 2-status, 3-exit test\n"); 236 | scanf("%d", &command); 237 | switch (command) { 238 | case 0: 239 | printf("turn off local monitor\n"); 240 | rs = LocalMonitorOff(); 241 | if (rs != SuccessStatus) { 242 | Log("LocalMonitorOff failed: %d\n", rs); 243 | return EXIT_FAILURE; 244 | } 245 | break; 246 | case 1: 247 | printf("turn on local monitor\n"); 248 | rs = LocalMonitorOn(); 249 | if (rs != SuccessStatus) { 250 | Log("LocalMonitorOn failed: %d\n", rs); 251 | return EXIT_FAILURE; 252 | } 253 | break; 254 | case 2: 255 | { 256 | bool bLocalMonitorOn = false; 257 | printf("get local monitor status\n"); 258 | rs = IsLocalMonitorOn(&bLocalMonitorOn); 259 | if (rs == SuccessStatus) { 260 | if (bLocalMonitorOn) 261 | printf("Local monitor setting is ON\n"); 262 | else 263 | printf("Local monitor setting is OFF\n"); 264 | } else { 265 | Log("IsLocalMonitorOn failed: %d\n", rs); 266 | return EXIT_FAILURE; 267 | } 268 | } 269 | break; 270 | default: 271 | break; 272 | } 273 | } 274 | #endif 275 | #ifdef TEST_WAIT_FOR_VIDEO_EVENT 276 | printf("Testing Wait for Video Event\n"); 277 | memset(&anEm, 0x0, sizeof(struct EventMap)); 278 | rs = TimedOut; 279 | dwTimeoutInMs = 5000; 280 | 281 | while (command < 5) { 282 | printf("Enter Command\n"); 283 | printf("Enter 0 to retrieve changes without waiting\n"); 284 | printf("Enter 1 to wait for event with 1 second timeout\n"); 285 | printf("Enter 2 to set Event Map\n"); 286 | printf("Enter 3 to set timeout value\n"); 287 | printf("Enter 4 to print out Event Map and Returned Event Map\n"); 288 | scanf("%d", &command); 289 | switch (command) { 290 | case 0: 291 | rs = WaitForVideoEvent(rc, anEm, &receivedEM, 0); 292 | Log("Status:[%d]\n", rs); 293 | break; 294 | case 1: 295 | { 296 | bool bModeStable = false; 297 | 298 | while (!bModeStable) { 299 | // Assume mode is unstable and wait for event 300 | rs = WaitForVideoEvent(rc, anEm, &receivedEM, 10000); 301 | printf("Event Map Received[%#x]\n", receivedEM); 302 | if (!receivedEM.bGeometryChanged) 303 | bModeStable = true; 304 | } 305 | } 306 | Log("Status:[%d]\n", rs); 307 | break; 308 | case 2: 309 | printf("Enter mask in 4 byte hex format:"); 310 | scanf("%x", &dwMask); 311 | printf("dwMask[%#x]\n", dwMask); 312 | memcpy((void *)&anEm, (void *)&dwMask, sizeof(dwMask)); 313 | break; 314 | case 3: 315 | printf("Enter timeout value in ms:"); 316 | scanf("%u", &dwTimeoutInMs); 317 | printf("Timeout value in ms: %u\n", dwTimeoutInMs); 318 | break; 319 | case 4: 320 | Log("Event Map Sent To Wait for Video Event\n"); 321 | Log("bPaletteChanged [%d]\n", anEm.bPaletteChanged); 322 | Log("bATTRChanged [%d]\n", anEm.bATTRChanged); 323 | Log("bSEQChanged [%d]\n", anEm.bSEQChanged); 324 | Log("bGCTLChanged [%d]\n", anEm.bGCTLChanged); 325 | Log("bGeometryChanged [%d]\n", anEm.bCRTCChanged); 326 | Log("bCRTCEXTChanged [%d]\n", anEm.bCRTCEXTChanged); 327 | Log("bPLTRAMChanged [%d]\n", anEm.bPLTRAMChanged); 328 | Log("bXCURCOLChanged [%d]\n", anEm.bXCURCOLChanged); 329 | Log("bXCURCTLChanged [%d]\n", anEm.bXCURCTLChanged); 330 | Log("bXCURPOSChanged [%d]\n", anEm.bXCURPOSChanged); 331 | Log("bDoorbellA [%d]\n", anEm.bDoorbellA); 332 | Log("bDoorbellB [%d]\n", anEm.bDoorbellB); 333 | Log("bGeometryChanged [%d]\n", anEm.bGeometryChanged); 334 | Log("bSnoopChanged [%d]\n", anEm.bSnoopChanged); 335 | Log("bTextFontChanged [%d]\n", anEm.bTextFontChanged); 336 | Log("bTextATTRChanged [%d]\n", anEm.bTextATTRChanged); 337 | Log("bTextASCIIChanged [%d]\n", anEm.bTextASCIIChanged); 338 | 339 | if (rs == SuccessStatus) { 340 | Log("\nEvent Map returned from Wait for Video Event\n"); 341 | Log("bPaletteChanged [%d]\n", receivedEM.bPaletteChanged); 342 | Log("bATTRChanged [%d]\n", receivedEM.bATTRChanged); 343 | Log("bSEQChanged [%d]\n", receivedEM.bSEQChanged); 344 | Log("bGCTLChanged [%d]\n", receivedEM.bGCTLChanged); 345 | Log("bGeometryChanged [%d]\n", receivedEM.bCRTCChanged); 346 | Log("bCRTCEXTChanged [%d]\n", receivedEM.bCRTCEXTChanged); 347 | Log("bPLTRAMChanged [%d]\n", receivedEM.bPLTRAMChanged); 348 | Log("bXCURCOLChanged [%d]\n", receivedEM.bXCURCOLChanged); 349 | Log("bXCURCTLChanged [%d]\n", receivedEM.bXCURCTLChanged); 350 | Log("bXCURPOSChanged [%d]\n", receivedEM.bXCURPOSChanged); 351 | Log("bDoorbellA [%d]\n", receivedEM.bDoorbellA); 352 | Log("bDoorbellB [%d]\n", receivedEM.bDoorbellB); 353 | Log("bGeometryChanged [%d]\n", receivedEM.bGeometryChanged); 354 | Log("bSnoopChanged [%d]\n", receivedEM.bSnoopChanged); 355 | Log("bTextFontChanged [%d]\n", receivedEM.bTextFontChanged); 356 | Log("bTextATTRChanged [%d]\n", receivedEM.bTextATTRChanged); 357 | Log("bTextASCIIChanged [%d]\n", receivedEM.bTextASCIIChanged); 358 | memset(&receivedEM, 0x0, sizeof(struct EventMap)); 359 | } else if (rs == TimedOut) 360 | Log("Timed out\n"); 361 | else 362 | Log("WaitForVideoEvent failed\n"); 363 | 364 | break; 365 | } 366 | } 367 | #endif 368 | #ifdef TEST_TSE_COUNTER 369 | printf("Testing TSE Counter\n"); 370 | memset(&anEm, 0x0, sizeof(struct EventMap)); 371 | memset(&receivedEM, 0x0, sizeof(struct EventMap)); 372 | anEm.bSnoopChanged = 1; 373 | rs = TimedOut; 374 | dwTimeoutInMs = 10; 375 | dw_tse_counter = 0; 376 | time_to_run_secs = TIME_LIMIT_IN_SECS; 377 | printf( 378 | "Enter TSE Counter Amount in Hex. Time in ms in digits. Time to run in seconds. Enter 0 0 0 to stop.\n"); 379 | scanf("%x %u %u", &dw_tse_counter, &dwTimeoutInMs, &time_to_run_secs); 380 | 381 | while (dw_tse_counter) { 382 | clock_gettime(CLOCK_REALTIME, &start_time); 383 | dw_frame_ct = 0; 384 | rs = SetTSECounter(dw_tse_counter); 385 | 386 | if (rs != SuccessStatus) { 387 | printf("Unable to set the TSE Counter.\n"); 388 | return EXIT_FAILURE; 389 | } 390 | 391 | do { 392 | rs = WaitForVideoEvent(rc, anEm, &receivedEM, 393 | dwTimeoutInMs); 394 | 395 | if (rs == SuccessStatus) { 396 | if (receivedEM.bSnoopChanged) 397 | ++dw_frame_ct; 398 | } else if (rs == TimedOut) { 399 | // Do nothing without timed out status 400 | } else { 401 | printf("WaitForVideoEvent failed rs: %d\n", rs); 402 | return EXIT_FAILURE; 403 | } 404 | 405 | clock_gettime(CLOCK_REALTIME, &end_time); 406 | time_diff(&start_time, &end_time, &res_time); 407 | } while (res_time.tv_sec < time_to_run_secs); 408 | 409 | f_avg_frames = (float) dw_frame_ct / (float) time_to_run_secs; 410 | printf( 411 | "Average Frame Per Second: %f Frame Count: %u Time: %u Timed Out ms: %u TSE Counter: %#x\n", 412 | f_avg_frames, dw_frame_ct, time_to_run_secs, 413 | dwTimeoutInMs, dw_tse_counter); 414 | printf( 415 | "Enter TSE Counter Amount in Hex. Time in ms in digits. Time to run in seconds. Enter 0 0 0 to stop.\n"); 416 | scanf("%x %u %u", &dw_tse_counter, &dwTimeoutInMs, 417 | &time_to_run_secs); 418 | } 419 | #endif 420 | 421 | rs = DeleteContext(rc); 422 | 423 | if (rs != SuccessStatus) { 424 | Log("Deleting context failed: %d\n", rs); 425 | return EXIT_FAILURE; 426 | } 427 | 428 | Log("Deleted RVAS context\n"); 429 | rs = Shutdown(); 430 | 431 | if (rs != SuccessStatus) { 432 | Log("Shutdown RVAS failed: %d\n", rs); 433 | return EXIT_FAILURE; 434 | } 435 | 436 | Log("End of RVAS test\n"); 437 | CloseLog(); 438 | 439 | return EXIT_SUCCESS; 440 | } 441 | -------------------------------------------------------------------------------- /espi_test/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0-only 2 | # 3 | # Copyright 2020 Aspeed Technology Inc. 4 | # 5 | ifdef INST 6 | ifeq ("$(origin INST)", "command line") 7 | INSTALL_DIR := $(INST) 8 | endif 9 | endif 10 | 11 | CFLAGS += -Wall -lpthread 12 | CC = $(CROSS_COMPILE)gcc 13 | 14 | all: oob-pch-test 15 | 16 | oob-pch-test: oob-pch-test.o 17 | $(CC) $(CFLAGS) oob-pch-test.o -o $@ 18 | 19 | .c.o: 20 | $(CC) $(CFLAGS) -c $< 21 | 22 | clean: 23 | rm -f oob-pch-test *.o 24 | 25 | install: 26 | cp oob-pch-test $(INSTALL_DIR) 27 | 28 | -------------------------------------------------------------------------------- /espi_test/aspeed-espi.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ */ 2 | /* 3 | * Copyright 2020 Aspeed Technology Inc. 4 | */ 5 | #ifndef _UAPI_LINUX_ASPEED_ESPI_H 6 | #define _UAPI_LINUX_ASPEED_ESPI_H 7 | 8 | #ifdef __KERNEL__ 9 | #include 10 | #include 11 | #else 12 | #include 13 | #include 14 | #endif 15 | 16 | /* 17 | * eSPI cycle type encoding 18 | * 19 | * Section 5.1 Cycle Types and Packet Format, 20 | * Intel eSPI Interface Base Specification, Rev 1.0, Jan. 2016. 21 | */ 22 | #define ESPI_PERIF_MEMRD32 0x00 23 | #define ESPI_PERIF_MEMRD64 0x02 24 | #define ESPI_PERIF_MEMWR32 0x01 25 | #define ESPI_PERIF_MEMWR64 0x03 26 | #define ESPI_PERIF_MSG 0x10 27 | #define ESPI_PERIF_MSG_D 0x11 28 | #define ESPI_PERIF_SUC_CMPLT 0x06 29 | #define ESPI_PERIF_SUC_CMPLT_D_MIDDLE 0x09 30 | #define ESPI_PERIF_SUC_CMPLT_D_FIRST 0x0b 31 | #define ESPI_PERIF_SUC_CMPLT_D_LAST 0x0d 32 | #define ESPI_PERIF_SUC_CMPLT_D_ONLY 0x0f 33 | #define ESPI_PERIF_UNSUC_CMPLT 0x0c 34 | #define ESPI_OOB_MSG 0x21 35 | #define ESPI_FLASH_READ 0x00 36 | #define ESPI_FLASH_WRITE 0x01 37 | #define ESPI_FLASH_ERASE 0x02 38 | #define ESPI_FLASH_SUC_CMPLT 0x06 39 | #define ESPI_FLASH_SUC_CMPLT_D_MIDDLE 0x09 40 | #define ESPI_FLASH_SUC_CMPLT_D_FIRST 0x0b 41 | #define ESPI_FLASH_SUC_CMPLT_D_LAST 0x0d 42 | #define ESPI_FLASH_SUC_CMPLT_D_ONLY 0x0f 43 | #define ESPI_FLASH_UNSUC_CMPLT 0x0c 44 | 45 | /* 46 | * eSPI packet format structure 47 | * 48 | * Section 5.1 Cycle Types and Packet Format, 49 | * Intel eSPI Interface Base Specification, Rev 1.0, Jan. 2016. 50 | */ 51 | struct espi_comm_hdr { 52 | uint8_t cyc; 53 | uint8_t len_h : 4; 54 | uint8_t tag : 4; 55 | uint8_t len_l; 56 | }; 57 | 58 | struct espi_perif_mem32 { 59 | uint8_t cyc; 60 | uint8_t len_h : 4; 61 | uint8_t tag : 4; 62 | uint8_t len_l; 63 | uint32_t addr_be; 64 | uint8_t data[]; 65 | } __attribute__((packed)); 66 | 67 | struct espi_perif_mem64 { 68 | uint8_t cyc; 69 | uint8_t len_h : 4; 70 | uint8_t tag : 4; 71 | uint8_t len_l; 72 | uint32_t addr_be; 73 | uint8_t data[]; 74 | } __attribute__((packed)); 75 | 76 | struct espi_perif_msg { 77 | uint8_t cyc; 78 | uint8_t len_h : 4; 79 | uint8_t tag : 4; 80 | uint8_t len_l; 81 | uint8_t msg_code; 82 | uint8_t msg_byte[4]; 83 | uint8_t data[]; 84 | } __attribute__((packed)); 85 | 86 | struct espi_perif_cmplt { 87 | uint8_t cyc; 88 | uint8_t len_h : 4; 89 | uint8_t tag : 4; 90 | uint8_t len_l; 91 | uint8_t data[]; 92 | } __attribute__((packed)); 93 | 94 | struct espi_oob_msg { 95 | uint8_t cyc; 96 | uint8_t len_h : 4; 97 | uint8_t tag : 4; 98 | uint8_t len_l; 99 | uint8_t data[]; 100 | }; 101 | 102 | struct espi_flash_rwe { 103 | uint8_t cyc; 104 | uint8_t len_h : 4; 105 | uint8_t tag : 4; 106 | uint8_t len_l; 107 | uint32_t addr_be; 108 | uint8_t data[]; 109 | } __attribute__((packed)); 110 | 111 | struct espi_flash_cmplt { 112 | uint8_t cyc; 113 | uint8_t len_h : 4; 114 | uint8_t tag : 4; 115 | uint8_t len_l; 116 | uint8_t data[]; 117 | } __attribute__((packed)); 118 | 119 | struct aspeed_espi_ioc { 120 | uint32_t pkt_len; 121 | uint8_t *pkt; 122 | }; 123 | 124 | /* 125 | * we choose the longest header and the max payload size 126 | * based on the Intel specification to define the maximum 127 | * eSPI packet length 128 | */ 129 | #define ESPI_PLD_LEN_MIN (1UL << 6) 130 | #define ESPI_PLD_LEN_MAX (1UL << 12) 131 | #define ESPI_PKT_LEN_MAX (sizeof(struct espi_perif_msg) + ESPI_PLD_LEN_MAX) 132 | 133 | #define __ASPEED_ESPI_IOCTL_MAGIC 0xb8 134 | 135 | /* peripheral channel (ch0) */ 136 | #define ASPEED_ESPI_PERIF_PC_GET_RX _IOR(__ASPEED_ESPI_IOCTL_MAGIC, \ 137 | 0x00, struct aspeed_espi_ioc) 138 | #define ASPEED_ESPI_PERIF_PC_PUT_TX _IOW(__ASPEED_ESPI_IOCTL_MAGIC, \ 139 | 0x01, struct aspeed_espi_ioc) 140 | #define ASPEED_ESPI_PERIF_NP_PUT_TX _IOW(__ASPEED_ESPI_IOCTL_MAGIC, \ 141 | 0x02, struct aspeed_espi_ioc) 142 | /* peripheral channel (ch1) */ 143 | #define ASPEED_ESPI_VW_GET_GPIO_VAL _IOR(__ASPEED_ESPI_IOCTL_MAGIC, \ 144 | 0x10, uint8_t) 145 | #define ASPEED_ESPI_VW_PUT_GPIO_VAL _IOW(__ASPEED_ESPI_IOCTL_MAGIC, \ 146 | 0x11, uint8_t) 147 | /* out-of-band channle (ch2) */ 148 | #define ASPEED_ESPI_OOB_GET_RX _IOR(__ASPEED_ESPI_IOCTL_MAGIC, \ 149 | 0x20, struct aspeed_espi_ioc) 150 | #define ASPEED_ESPI_OOB_PUT_TX _IOW(__ASPEED_ESPI_IOCTL_MAGIC, \ 151 | 0x21, struct aspeed_espi_ioc) 152 | /* flash channel (ch3) */ 153 | #define ASPEED_ESPI_FLASH_GET_RX _IOR(__ASPEED_ESPI_IOCTL_MAGIC, \ 154 | 0x30, struct aspeed_espi_ioc) 155 | #define ASPEED_ESPI_FLASH_PUT_TX _IOW(__ASPEED_ESPI_IOCTL_MAGIC, \ 156 | 0x31, struct aspeed_espi_ioc) 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /espi_test/oob-pch-test.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0+ 2 | /* 3 | * Copyright 2020 Aspeed Technology Inc. 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "aspeed-espi.h" 18 | 19 | enum PCH_REQ_TYPE { 20 | PCH_REQ_TEMP, 21 | PCH_REQ_RTC, 22 | PCH_REQS, 23 | }; 24 | 25 | struct oob_context { 26 | int dev_fd; 27 | char dev_path[256]; 28 | }; 29 | static struct oob_context oob_ctx[1]; 30 | 31 | static const char opt_short[] = "hd:tr"; 32 | 33 | static const struct option opt_long [] = { 34 | { "help", no_argument, NULL, 'h' }, 35 | { "dev", required_argument, NULL, 'd' }, 36 | { "temperature", no_argument, NULL, 't' }, 37 | { "rtc", no_argument, NULL, 'r' }, 38 | { 0, 0, 0, 0 } 39 | }; 40 | 41 | static void print_usage(int argc, char **argv) 42 | { 43 | printf( 44 | "Usage: %s [options]\n" 45 | "eSPI OOB PCH Temperature/RTC test\n\n" 46 | "Options:\n" 47 | " -h | --help Print this message\n" 48 | " -d | --dev eSPI oob device node\n" 49 | " -t | --temperature PCH Temperature request\n" 50 | " -r | --rtc PCH RTC request\n" 51 | "", 52 | argv[0]); 53 | } 54 | 55 | static void print_hexdump(uint8_t *buf, uint32_t len) 56 | { 57 | int i; 58 | 59 | for (i = 0; i < len; ++i) { 60 | if (i && (i % 16 == 0)) 61 | printf("\n"); 62 | printf("%02x ", buf[i]); 63 | } 64 | printf("\n"); 65 | } 66 | 67 | /* 68 | * Intel 300 Series and Intel C240 Series Chipset Famliy Platform Controller Hub 69 | * 70 | * eSPI Slave to PCH: Request for PCH Temperature 71 | * +-----------------------------------------------+ 72 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 73 | * +-----------------------------------------------+ 74 | * | eSPI cycle type: OOB message 21h | 75 | * +-----------------------------------------------+ 76 | * | Tag[3:0] | Length[11:8]=0h | 77 | * +-----------------------------------------------+ 78 | * | Length[7:0]=04h | 79 | * +-----------------------------------------------+ 80 | * | Dst Slv Addr[7:1]=01h (PCH OOB Handler) | 0 | 81 | * +-----------------------------------------------+ 82 | * | Command Code=01h (Get_PCH_TEMP) | 83 | * +-----------------------------------------------+ 84 | * | Byte Count=01h | 85 | * +-----------------------------------------------+ 86 | * | Src Slv Addr[7:0]=0Fh (eSPI slave 0/EC) | 1 | 87 | * +-----------------------------------------------+ 88 | * 89 | * 90 | * PCH to eSPI Slave: Response with PCH Temperature 91 | * +-----------------------------------------------+ 92 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 93 | * +-----------------------------------------------+ 94 | * | eSPI cycle type: OOB message 21h | 95 | * +-----------------------------------------------+ 96 | * | Tag[3:0] | Length[11:8]=0h | 97 | * +-----------------------------------------------+ 98 | * | Length[7:0]=05h | 99 | * +-----------------------------------------------+ 100 | * | Dst Slv Addr[7:0]=0Eh (eSPI slave 0/EC) | 0 | 101 | * +-----------------------------------------------+ 102 | * | Command Code=01h (Get_PCH_TEMP) | 103 | * +-----------------------------------------------+ 104 | * | Byte Count=02h | 105 | * +-----------------------------------------------+ 106 | * | Src Slv Addr[7:1]=01h (PCH OOB Handler) | 1 | 107 | * +-----------------------------------------------+ 108 | * | PCH Temperature Data[7:0] | 109 | * +-----------------------------------------------+ 110 | */ 111 | static int oob_req_pch_temp(int fd, struct espi_oob_msg *oob_pkt) 112 | { 113 | int rc; 114 | struct aspeed_espi_ioc ioc; 115 | uint32_t cyc, tag, len; 116 | 117 | ioc.pkt = (uint8_t *)oob_pkt; 118 | 119 | oob_pkt->cyc = ESPI_OOB_MSG; 120 | oob_pkt->tag = 0x0; 121 | oob_pkt->len_h = 0x0; 122 | oob_pkt->len_l = 0x4; 123 | 124 | oob_pkt->data[0] = 0x2; 125 | oob_pkt->data[1] = 0x1; 126 | oob_pkt->data[2] = 0x1; 127 | oob_pkt->data[3] = 0xf; 128 | 129 | ioc.pkt_len = ((oob_pkt->len_h << 8) | oob_pkt->len_l) + sizeof(*oob_pkt); 130 | rc = ioctl(fd, ASPEED_ESPI_OOB_PUT_TX, &ioc); 131 | if (rc) { 132 | printf("ASPEED_ESPI_OOB_PUT_TX ioctl failed, rc=%d\n", rc); 133 | return rc; 134 | } 135 | 136 | cyc = oob_pkt->cyc; 137 | tag = oob_pkt->tag; 138 | len = (oob_pkt->len_h << 8) | (oob_pkt->len_l & 0xff); 139 | printf("==== Transmit TX Packet ====\n"); 140 | printf("cyc=0x%02x, tag=0x%02x, len=0x%04x\n", cyc, tag, len); 141 | print_hexdump(oob_pkt->data, (len)? len : ESPI_PLD_LEN_MAX); 142 | 143 | ioc.pkt_len = ESPI_PKT_LEN_MAX; 144 | rc = ioctl(fd, ASPEED_ESPI_OOB_GET_RX, &ioc); 145 | if (rc) { 146 | printf("ASPEED_ESPI_OOB_GET_RX ioctl failed, rc=%d\n", rc); 147 | return rc; 148 | } 149 | 150 | cyc = oob_pkt->cyc; 151 | tag = oob_pkt->tag; 152 | len = (oob_pkt->len_h << 8) | (oob_pkt->len_l & 0xff); 153 | printf("==== Receive RX Packet ====\n"); 154 | printf("cyc=0x%02x, tag=0x%02x, len=0x%04x\n", cyc, tag, len); 155 | print_hexdump(oob_pkt->data, (len)? len : ESPI_PLD_LEN_MAX); 156 | 157 | return 0; 158 | } 159 | 160 | /* 161 | * Intel 300 Series and Intel C240 Series Chipset Famliy Platform Controller Hub 162 | * 163 | * eSPI Slave to PCH: Request for RTC Time 164 | * +-----------------------------------------------+ 165 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 166 | * +-----------------------------------------------+ 167 | * | eSPI cycle type: OOB message 21h | 168 | * +-----------------------------------------------+ 169 | * | Tag[3:0] | Length[11:8]=0h | 170 | * +-----------------------------------------------+ 171 | * | Length[7:0]=04h | 172 | * +-----------------------------------------------+ 173 | * | Dst Slv Addr[7:1]=01h (PCH OOB Handler) | 0 | 174 | * +-----------------------------------------------+ 175 | * | Command Code=02h (Get_PCH_RTC_Time) | 176 | * +-----------------------------------------------+ 177 | * | Byte Count=01h | 178 | * +-----------------------------------------------+ 179 | * | Src Slv Addr[7:0]=0Fh (eSPI slave 0/EC) | 1 | 180 | * +-----------------------------------------------+ 181 | * 182 | * 183 | * PCH to eSPI Slave: Response with PCH RTC Time 184 | * +-----------------------------------------------+ 185 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 186 | * +-----------------------------------------------+ 187 | * | eSPI cycle type: OOB message 21h | 188 | * +-----------------------------------------------+ 189 | * | Tag[3:0] | Length[11:8]=0h | 190 | * +-----------------------------------------------+ 191 | * | Length[7:0]=0Ch | 192 | * +-----------------------------------------------+ 193 | * | Dst Slv Addr[7:0]=0Eh (eSPI slave 0/EC) | 0 | 194 | * +-----------------------------------------------+ 195 | * | Command Code=02h (Get_PCH_RTC_Time) | 196 | * +-----------------------------------------------+ 197 | * | Byte Count=09h | 198 | * +-----------------------------------------------+ 199 | * | Src Slv Addr[7:1]=01h (PCH OOB Handler) | 1 | 200 | * +-----------------------------------------------+ 201 | * | Reserved | DM | HF | DS | 202 | * +-----------------------------------------------+ 203 | * | PCH RTC Time: Seconds | 204 | * +-----------------------------------------------+ 205 | * | PCH RTC Time: Minutes | 206 | * +-----------------------------------------------+ 207 | * | PCH RTC Time: Hours | 208 | * +-----------------------------------------------+ 209 | * | PCH RTC Time: Day of Week | 210 | * +-----------------------------------------------+ 211 | * | PCH RTC Time: Day of Month | 212 | * +-----------------------------------------------+ 213 | * | PCH RTC Time: Month | 214 | * +-----------------------------------------------+ 215 | * | PCH RTC Time: Year | 216 | * +-----------------------------------------------+ 217 | */ 218 | static int oob_req_pch_rtc(int fd, struct espi_oob_msg *oob_pkt) 219 | { 220 | int rc; 221 | struct aspeed_espi_ioc ioc; 222 | uint32_t cyc, tag, len; 223 | 224 | ioc.pkt = (uint8_t *)oob_pkt; 225 | 226 | oob_pkt->cyc = ESPI_OOB_MSG; 227 | oob_pkt->tag = 0x0; 228 | oob_pkt->len_h = 0x0; 229 | oob_pkt->len_l = 0x4; 230 | 231 | oob_pkt->data[0] = 0x2; 232 | oob_pkt->data[1] = 0x2; 233 | oob_pkt->data[2] = 0x1; 234 | oob_pkt->data[3] = 0xf; 235 | 236 | ioc.pkt_len = ((oob_pkt->len_h << 8) | oob_pkt->len_l) + sizeof(*oob_pkt); 237 | rc = ioctl(fd, ASPEED_ESPI_OOB_PUT_TX, &ioc); 238 | if (rc) { 239 | printf("ASPEED_ESPI_OOB_PUT_TX ioctl failed, rc=%d\n", rc); 240 | return rc; 241 | } 242 | 243 | cyc = oob_pkt->cyc; 244 | tag = oob_pkt->tag; 245 | len = (oob_pkt->len_h << 8) | (oob_pkt->len_l & 0xff); 246 | printf("==== Transmit TX Packet ====\n"); 247 | printf("cyc=0x%02x, tag=0x%02x, len=0x%04x\n", cyc, tag, len); 248 | print_hexdump(oob_pkt->data, (len)? len : ESPI_PLD_LEN_MAX); 249 | 250 | ioc.pkt_len = ESPI_PKT_LEN_MAX; 251 | rc = ioctl(fd, ASPEED_ESPI_OOB_GET_RX, &ioc); 252 | if (rc) { 253 | printf("ASPEED_ESPI_OOB_GET_RX ioctl failed, rc=%d\n", rc); 254 | return rc; 255 | } 256 | 257 | cyc = oob_pkt->cyc; 258 | tag = oob_pkt->tag; 259 | len = (oob_pkt->len_h << 8) | (oob_pkt->len_l & 0xff); 260 | printf("==== Receive RX Packet ====\n"); 261 | printf("cyc=0x%02x, tag=0x%02x, len=0x%04x\n", cyc, tag, len); 262 | print_hexdump(oob_pkt->data, (len)? len : ESPI_PLD_LEN_MAX); 263 | 264 | return 0; 265 | } 266 | 267 | int main(int argc, char *argv[]) 268 | { 269 | int rc; 270 | char opt; 271 | uint32_t pch_req = PCH_REQS; 272 | struct espi_oob_msg *oob_pkt; 273 | 274 | while ((opt=getopt_long(argc, argv, opt_short, opt_long, NULL)) != (char)-1) { 275 | switch(opt) { 276 | case 'h': 277 | print_usage(argc, argv); 278 | return 0; 279 | case 'd': 280 | strcpy(oob_ctx->dev_path, optarg); 281 | break; 282 | case 't': 283 | pch_req = PCH_REQ_TEMP; 284 | break; 285 | case 'r': 286 | pch_req = PCH_REQ_RTC; 287 | break; 288 | default: 289 | print_usage(argc, argv); 290 | return -1; 291 | } 292 | } 293 | 294 | oob_pkt = (struct espi_oob_msg *)malloc(ESPI_PKT_LEN_MAX); 295 | if (!oob_pkt) { 296 | printf("cannot allocate OOB packet\n"); 297 | return -1; 298 | } 299 | 300 | oob_ctx->dev_fd = open(oob_ctx->dev_path, O_RDWR); 301 | if (oob_ctx->dev_fd == -1) { 302 | printf("cannot open eSPI OOB devie\n"); 303 | return -1; 304 | } 305 | 306 | switch (pch_req) { 307 | case PCH_REQ_TEMP: 308 | rc = oob_req_pch_temp(oob_ctx->dev_fd, oob_pkt); 309 | break; 310 | case PCH_REQ_RTC: 311 | rc = oob_req_pch_rtc(oob_ctx->dev_fd, oob_pkt); 312 | break; 313 | default: 314 | printf("Unknown PCH request type: %u\n", pch_req); 315 | rc = -1; 316 | break; 317 | } 318 | 319 | free(oob_pkt); 320 | close(oob_ctx->dev_fd); 321 | 322 | return rc; 323 | } 324 | -------------------------------------------------------------------------------- /i2c-slave-mqueue/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CC = $(CROSS_COMPILE)gcc 8 | INCLUDE = . 9 | OBJS = 10 | LDLIBS = -lc -lrt -lgcc 11 | EXTRA_FLAGS = -lpthread 12 | CFLAGS += -Wall -O2 13 | EXEC_NAME = i2c-slave-mqueue 14 | 15 | all: $(EXEC_NAME) 16 | 17 | $(EXEC_NAME): $(EXEC_NAME).o 18 | $(CC) $(CFLAGS) $(OBJS) $(EXEC_NAME).o -o $@ $(LDLIBS) $(EXTRA_FLAGS) 19 | 20 | $(EXEC_NAME).o: $(OBJS) $(EXEC_NAME).c 21 | $(CC) $(CFLAGS) -l$(INCLUDE) -c $(EXEC_NAME).c 22 | 23 | clean: 24 | rm -f $(EXEC_NAME).elf $(EXEC_NAME).gdb $(EXEC_NAME).o $(EXEC_NAME) 25 | 26 | install: 27 | cp $(EXEC_NAME) $(INSTALL_DIR) 28 | -------------------------------------------------------------------------------- /i2c-slave-mqueue/i2c-slave-mqueue.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright 2020 Aspeed Technology Inc. 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | int i, r; 16 | struct pollfd pfd; 17 | struct timespec ts; 18 | unsigned char data[256]; 19 | 20 | pfd.fd = open(argv[1], O_RDONLY | O_NONBLOCK); 21 | if (pfd.fd < 0) 22 | return -1; 23 | 24 | pfd.events = POLLPRI; 25 | 26 | while (1) { 27 | r = poll(&pfd, 1, 5000); 28 | 29 | if (r < 0) 30 | break; 31 | 32 | if (r == 0 || !(pfd.revents & POLLPRI)) 33 | continue; 34 | 35 | lseek(pfd.fd, 0, SEEK_SET); 36 | r = read(pfd.fd, data, sizeof(data)); 37 | if (r <= 0) 38 | continue; 39 | 40 | clock_gettime(CLOCK_MONOTONIC, &ts); 41 | printf("[%ld.%.9ld] :", ts.tv_sec, ts.tv_nsec); 42 | for (i = 0; i < r; i++) 43 | printf(" %02x", data[i]); 44 | printf("\n"); 45 | } 46 | 47 | close(pfd.fd); 48 | 49 | return 0; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /i2c-test/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CC = $(CROSS_COMPILE)gcc 8 | INCLUDE = . 9 | OBJS = 10 | LDLIBS = -lc -lrt -lgcc 11 | EXTRA_FLAGS = -lpthread 12 | CFLAGS += -Wall -O2 13 | EXEC_NAME = i2c-test 14 | 15 | all: $(EXEC_NAME) 16 | 17 | $(EXEC_NAME): $(EXEC_NAME).o 18 | $(CC) $(CFLAGS) $(OBJS) $(EXEC_NAME).o -o $@ $(LDLIBS) $(EXTRA_FLAGS) 19 | 20 | $(EXEC_NAME).o: $(OBJS) $(EXEC_NAME).c 21 | $(CC) $(CFLAGS) -l$(INCLUDE) -c $(EXEC_NAME).c 22 | 23 | clean: 24 | rm -f $(EXEC_NAME).elf $(EXEC_NAME).gdb $(EXEC_NAME).o $(EXEC_NAME) 25 | 26 | install: 27 | cp $(EXEC_NAME) $(INSTALL_DIR) 28 | -------------------------------------------------------------------------------- /i2c-test/i2c-test.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright Aspeed Technology Inc. 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | /*****************************************************************************/ 57 | #define DEF_I2C_ADDR 0x04 58 | 59 | #define DEF_THREAD_CH 12 60 | #define DEF_PAIR0_DEV 0 61 | #define DEF_PAIR1_DEV 1 62 | 63 | #define DEF_PAIR1_ADDR 0x03 64 | #define DEF_PAIR2_ADDR 0x04 65 | #define TIMEOUT 10 66 | 67 | #define DEF_SLAVE_ADDR 0x3a 68 | #define DEF_XFER_BUF_SIZE 128 69 | 70 | int debug = 0; 71 | struct thread_data { 72 | char filename[512]; 73 | uint8_t slave_addr; 74 | 75 | int ack_send_length; 76 | int loop_cnt; 77 | int continuous_flag; 78 | int random_flag; 79 | int xfer_size; 80 | unsigned char *xfer_buf; 81 | unsigned char *pattern; 82 | int address; 83 | int bus; 84 | struct thread_data *pair_thread_data; 85 | }; 86 | 87 | static void usage(FILE *fp, int argc, char **argv) 88 | { 89 | fprintf(fp, 90 | "Usage: %s [options]\n\n" 91 | "Options:\n" 92 | " -h | --help Print this message\n" 93 | " -m | --master master mode \n" 94 | " -s | --slave slave mode\n" 95 | " -b | --bus test bus number[default : 0]\n" 96 | " -a | --address slav address [default : 0x04]\n" 97 | " -z | --tx_size transfer size[default : 255]\n" 98 | " -c | --continuous contunuous\n" 99 | " -l | --loop loop test\n" 100 | " -p | --pair pair on the same board[I2c-1 <-> I2c-2]\n" 101 | " -e | --echo echo (0: tx 1: respond)\n" 102 | " -r | --random test pattern is random\n" 103 | " -u | --multi multi master test (-1: only echo1, >0: echo0 bus)\n" 104 | " -d | --debug debug mode\n" 105 | " -i | --disable disable the slave mode" 106 | "example:\n" 107 | "master and slave test:\n" 108 | " boardA : $./i2c-test -m -a0x04 -b0\n" 109 | " boardB : $./i2c-test -s -a0x04 -b0\n" 110 | "echo test:\n" 111 | " boardA : $./i2c-test -e0\n" 112 | " boardB : $./i2c-test -e1\n" 113 | "one board test:\n" 114 | " boardA : $./i2c-test -p\n" 115 | " : $./i2c-test -p -e0\n" 116 | "multi master test:\n" 117 | " boardA : $./i2c-test -u0 -b1 -a0x4 ( a=(b+1)*2 ) \n" 118 | " boardB : $./i2c-test -u-1 -b1 \n" 119 | " boardA bus should equal boardB bus\n" 120 | " boardA address should equal (bus+1)*2\n" 121 | "disable slave mode:\n" 122 | "$./i2c-test -i -b0" 123 | "", 124 | argv[0]); 125 | } 126 | 127 | static const char short_options [] = "hm:s:c:prdie:s:l:b:a:u:"; 128 | 129 | static const struct option 130 | long_options [] = { 131 | { "help", no_argument, NULL, 'h' }, 132 | { "master", no_argument, NULL, 'm' }, 133 | { "slave", no_argument, NULL, 's' }, 134 | { "continuous", no_argument, NULL, 'c' }, 135 | { "bus", required_argument, NULL, 'b' }, 136 | { "tx_size", required_argument, NULL, 's' }, 137 | { "loop", required_argument, NULL, 'l' }, 138 | { "pair", no_argument, NULL, 'p' }, 139 | { "echo", required_argument, NULL, 'e' }, 140 | { "random", no_argument, NULL, 'r' }, 141 | { "address", required_argument, NULL, 'a' }, 142 | { "multi", required_argument, NULL, 'u' }, 143 | { "debug", no_argument, NULL, 'd' }, 144 | { "disable", no_argument, NULL, 'i' }, 145 | 146 | { 0, 0, 0, 0 } 147 | }; 148 | 149 | static void print_buf(unsigned char *pattern, int size) 150 | { 151 | int i; 152 | 153 | for (i = 0; i < size; i++) { 154 | if (!(i % 16)) 155 | printf("\n"); 156 | printf("%2x ", pattern[i]); 157 | } 158 | 159 | printf("\n"); 160 | } 161 | 162 | static int compare_pattern(unsigned char *pattern0, unsigned char *pattern1, 163 | int size) 164 | { 165 | int i; 166 | for (i = 0; i < size; i++) { 167 | if (pattern0[i] != pattern1[i]) { 168 | return 0; 169 | } 170 | } 171 | return 1; 172 | } 173 | 174 | static void test_pattern_prepare(unsigned char *pattern, int size) 175 | { 176 | int i, j; 177 | for (i = 0; i < size; i++) { 178 | j = i % 0xff; 179 | pattern[i] = j; 180 | } 181 | } 182 | 183 | static void random_pattern_prepare(unsigned char *pattern, int size) 184 | { 185 | int i; 186 | FILE *fp; 187 | int randno; 188 | 189 | if ((fp = fopen("/dev/urandom", "r")) == NULL) { 190 | fprintf(stderr, "Error! Could not open /dev/urandom for read\n"); 191 | exit(EXIT_FAILURE); 192 | } 193 | 194 | randno = fgetc(fp); 195 | 196 | for (i = 0; i < size; i++) { 197 | randno = fgetc(fp); 198 | pattern[i] = randno % 0xff; 199 | } 200 | 201 | fclose(fp); 202 | } 203 | 204 | void *i2c_master_thread(void *arg) 205 | { 206 | struct thread_data *master_data = (struct thread_data *) arg; 207 | int loop_cnt = master_data->loop_cnt; 208 | int continuous_flag = master_data->continuous_flag; 209 | int xfer_length = master_data->xfer_size; 210 | uint8_t *data = master_data->xfer_buf; 211 | int fd; 212 | int result = 0; 213 | int xfer_cnt = 0; 214 | 215 | if(!continuous_flag) 216 | printf("MM loop_cnt %d\n", loop_cnt); 217 | 218 | fd = open(master_data->filename, O_RDWR); 219 | if (fd < 0) { 220 | printf("can't open %s \n", master_data->filename); 221 | return NULL; 222 | } 223 | 224 | if (ioctl(fd, I2C_SLAVE, master_data->slave_addr) < 0) { 225 | perror("i2cSetAddress"); 226 | return NULL; 227 | } 228 | 229 | while (1) { 230 | if (debug) printf("[%d]:Mw [%x] len %d \n", xfer_cnt, master_data->slave_addr, xfer_length); 231 | if (write(fd, data, xfer_length) != xfer_length) { 232 | perror("write fail \n"); 233 | result = 1; 234 | break; 235 | } 236 | 237 | if(!continuous_flag) { 238 | loop_cnt--; 239 | if(!loop_cnt) break; 240 | } 241 | xfer_cnt++; 242 | if (debug) sleep(1); 243 | } 244 | 245 | close(fd); 246 | 247 | if (debug) printf("master thread end \n"); 248 | 249 | if(result) 250 | return (void *)1; 251 | else 252 | return NULL; 253 | 254 | } 255 | 256 | void *i2c_slave_thread(void *arg) 257 | { 258 | struct thread_data *slave_data = (struct thread_data *) arg; 259 | int loop_cnt = slave_data->loop_cnt; 260 | int continuous_flag = slave_data->continuous_flag; 261 | // int xfer_length = slave_data->xfer_size; 262 | uint8_t *data = slave_data->xfer_buf; 263 | 264 | int i, r; 265 | struct pollfd pfd; 266 | struct timespec ts; 267 | int result = 0; 268 | 269 | if(!continuous_flag) 270 | printf("SS loop_cnt %d\n", loop_cnt); 271 | 272 | pfd.fd = open(slave_data->filename, O_RDONLY | O_NONBLOCK); 273 | if (pfd.fd < 0) { 274 | printf("%s not find \n", slave_data->filename); 275 | return NULL; 276 | } 277 | 278 | pfd.events = POLLPRI; 279 | 280 | while (1) { 281 | r = poll(&pfd, 1, 5000); 282 | if (r < 0) 283 | break; 284 | 285 | if (r == 0 || !(pfd.revents & POLLPRI)) 286 | continue; 287 | 288 | lseek(pfd.fd, 0, SEEK_SET); 289 | r = read(pfd.fd, data, 512); 290 | if (r <= 0) 291 | continue; 292 | 293 | if(debug || continuous_flag) { 294 | clock_gettime(CLOCK_MONOTONIC, &ts); 295 | printf("[%ld.%.9ld] :", ts.tv_sec, ts.tv_nsec); 296 | for (i = 0; i < r; i++) 297 | printf(" %02x", data[i]); 298 | printf("\n"); 299 | } 300 | 301 | // if(xfer_length != r) 302 | // printf("rx length fail %d %d \n", xfer_length, r); 303 | 304 | 305 | if(compare_pattern(slave_data->xfer_buf, slave_data->pattern, slave_data->xfer_size + 1)) { 306 | printf("compare fail ----- \n"); 307 | result = 1; 308 | break; 309 | } 310 | 311 | if(!continuous_flag) { 312 | loop_cnt--; 313 | if(!loop_cnt) break; 314 | } 315 | 316 | } 317 | 318 | close(pfd.fd); 319 | if (debug) printf("slave thread end \n"); 320 | 321 | 322 | if(result) 323 | return (void *)1; 324 | else 325 | return NULL; 326 | 327 | 328 | } 329 | 330 | 331 | int main(int argc, char *argv[]) 332 | { 333 | char option; 334 | 335 | pthread_t pthread_master_tx; 336 | pthread_t pthread_slave_rx; 337 | struct thread_data data_pthread_master_tx; 338 | struct thread_data data_pthread_slave_rx; 339 | 340 | void *master_ret, *slave_ret; 341 | int master_flag = 0; 342 | int slave_flag = 0; 343 | int loop_cnt = 0; 344 | int xfer_size = 0; 345 | unsigned char pattern_buf[2*DEF_XFER_BUF_SIZE]; 346 | unsigned char recv_buf[2*DEF_XFER_BUF_SIZE]; 347 | 348 | data_pthread_master_tx.xfer_size = DEF_XFER_BUF_SIZE; 349 | data_pthread_slave_rx.xfer_size = DEF_XFER_BUF_SIZE; 350 | 351 | //i2c-test -m /dev/i2c0 -s /sys/bus/i2c/devices/i2c-6/6-003a/slave-mqueue 352 | // -a 0x3a -c 1 -l size 353 | test_pattern_prepare(pattern_buf, DEF_XFER_BUF_SIZE); 354 | 355 | printf("==== test pattern ==== \n"); 356 | print_buf(pattern_buf, DEF_XFER_BUF_SIZE); 357 | printf("================= \n"); 358 | 359 | data_pthread_master_tx.pattern = pattern_buf; 360 | data_pthread_slave_rx.pattern = pattern_buf; 361 | 362 | while ((option = getopt_long(argc, argv, short_options, long_options, NULL) 363 | ) != (char) - 1) { 364 | switch (option) { 365 | case 'h': 366 | usage(stdout, argc, argv); 367 | exit(EXIT_SUCCESS); 368 | break; 369 | case 'a': //master for slave address 370 | data_pthread_master_tx.slave_addr = strtoul(optarg, 0, 0); 371 | data_pthread_slave_rx.slave_addr = strtoul(optarg, 0, 0); 372 | break; 373 | case 'm': 374 | /* -m /dev/i2c0 */ 375 | master_flag = 1; 376 | data_pthread_master_tx.xfer_buf = pattern_buf; 377 | strcpy(data_pthread_master_tx.filename, optarg); 378 | break; 379 | case 's': 380 | /* -s /sys/bus/i2c/devices/i2c-6/6-003a/slave-mqueue */ 381 | slave_flag = 1; 382 | data_pthread_slave_rx.xfer_buf = recv_buf; 383 | strcpy(data_pthread_slave_rx.filename, optarg); 384 | break; 385 | case 'c': //count 386 | loop_cnt = strtoul(optarg, 0, 0); 387 | data_pthread_master_tx.loop_cnt = loop_cnt; 388 | data_pthread_slave_rx.loop_cnt = loop_cnt; 389 | break; 390 | case 'l': //length 391 | xfer_size = strtoul(optarg, 0, 0); 392 | data_pthread_master_tx.xfer_size = xfer_size; 393 | data_pthread_slave_rx.xfer_size = xfer_size; 394 | break; 395 | case 'r': 396 | data_pthread_master_tx.random_flag = 1; 397 | data_pthread_slave_rx.random_flag = 1; 398 | random_pattern_prepare(pattern_buf, DEF_XFER_BUF_SIZE); 399 | break; 400 | case 'd': 401 | debug = 1; 402 | break; 403 | default: 404 | usage(stdout, argc, argv); 405 | exit(EXIT_FAILURE); 406 | break; 407 | } 408 | } 409 | 410 | if(loop_cnt == 0) { 411 | //if no loop cnt, will be continuous test 412 | data_pthread_master_tx.continuous_flag = 1; 413 | data_pthread_slave_rx.continuous_flag = 1; 414 | } else { 415 | data_pthread_master_tx.continuous_flag = 0; 416 | data_pthread_slave_rx.continuous_flag = 0; 417 | } 418 | 419 | if (!master_flag && !slave_flag) { 420 | usage(stdout, argc, argv); 421 | exit(EXIT_FAILURE); 422 | } 423 | 424 | if (master_flag) { 425 | printf("master : [%s] : ", data_pthread_master_tx.filename); 426 | pthread_create(&(pthread_master_tx), NULL, i2c_master_thread, 427 | &data_pthread_master_tx); 428 | printf("write slave address [0x%x]\n", data_pthread_master_tx.slave_addr); 429 | } 430 | 431 | if (slave_flag) { 432 | printf("slave : [%s]\n", data_pthread_slave_rx.filename); 433 | pthread_create(&(pthread_slave_rx), NULL, i2c_slave_thread, 434 | &data_pthread_slave_rx); 435 | } 436 | 437 | if (master_flag) { 438 | pthread_join(pthread_master_tx, &master_ret); 439 | if (master_ret == PTHREAD_CANCELED) 440 | printf("The thread was canceled - "); 441 | if(debug) printf("Returned value %d - ", (int)master_ret); 442 | } 443 | 444 | if (slave_flag) { 445 | pthread_join(pthread_slave_rx, &slave_ret); 446 | if (slave_ret == PTHREAD_CANCELED) 447 | printf("The thread was canceled - "); 448 | 449 | if(debug) printf("Returned value %d - ", (int)slave_ret); 450 | } 451 | 452 | if (master_ret || slave_ret) printf(" ================= Fail =================\n"); 453 | else printf(" ================= Pass =================\n"); 454 | 455 | return 0; 456 | } 457 | -------------------------------------------------------------------------------- /i3c-test/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CC = $(CROSS_COMPILE)gcc 8 | INCLUDE = . 9 | OBJS = 10 | LDLIBS = -lc -lrt -lgcc 11 | EXTRA_FLAGS = -lpthread 12 | CFLAGS += -Wall -O2 13 | EXEC_NAME = i3c-test 14 | 15 | all: $(EXEC_NAME) 16 | 17 | $(EXEC_NAME): $(EXEC_NAME).o 18 | $(CC) $(CFLAGS) $(OBJS) $(EXEC_NAME).o -o $@ $(LDLIBS) $(EXTRA_FLAGS) 19 | 20 | $(EXEC_NAME).o: $(OBJS) $(EXEC_NAME).c 21 | $(CC) $(CFLAGS) -l$(INCLUDE) -c $(EXEC_NAME).c 22 | 23 | clean: 24 | rm -f $(EXEC_NAME).elf $(EXEC_NAME).gdb $(EXEC_NAME).o $(EXEC_NAME) 25 | 26 | install: 27 | cp $(EXEC_NAME) $(INSTALL_DIR) 28 | -------------------------------------------------------------------------------- /i3c-test/i3c-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #define I3C_M_CCC 0x9000 28 | 29 | 30 | typedef unsigned char u8; 31 | typedef signed char s8; 32 | 33 | typedef unsigned long int u32; 34 | typedef signed long int s32; 35 | 36 | typedef unsigned short int u16; 37 | typedef signed short int s16; 38 | 39 | static void 40 | usage(FILE *fp, int argc, char **argv) 41 | { 42 | fprintf(fp, 43 | "Usage: %s [options]\n\n" 44 | "Options:\n" 45 | " -h | --help Print this message\n" 46 | " -a | --address/cmd_id address or ccc_cmd id\n" 47 | " -r | --read read length \n" 48 | " -w | --write write length \n" 49 | " -s | --smbus smbus transfer \n" 50 | " -c | --ccc ccc cmd \n" 51 | " -d | --dev device node \n" 52 | "", 53 | argv[0]); 54 | } 55 | 56 | static const char short_options [] = "ha:r:w:d:c:s"; 57 | 58 | static const struct option 59 | long_options [] = { 60 | { "help", no_argument, NULL, 'h' }, 61 | { "addr", required_argument, NULL, 'a' }, 62 | { "read", required_argument, NULL, 'r' }, 63 | { "write", required_argument, NULL, 'w' }, 64 | { "device", required_argument, NULL, 'd' }, 65 | { "ccc", required_argument, NULL, 'c' }, 66 | { "smbus", no_argument, NULL, 's' }, 67 | { 0, 0, 0, 0 } 68 | }; 69 | 70 | unsigned int StrToHex(char *p) 71 | { 72 | int i, sum; 73 | int temp, length; 74 | char c; 75 | sum = 0; 76 | length = strlen(p); 77 | for( i = 0; i < (length) ; i++ ) 78 | { 79 | c = *p; 80 | if( c >= 'a' && c <= 'z') { 81 | temp = c - 87; 82 | sum += ((temp) << (4*(length - i - 1))); 83 | } else if( c >= 'A' && c <= 'Z') { 84 | temp = c - 55; 85 | sum += ((temp) << (4*(length - i - 1))); 86 | } else { 87 | temp = c - 48; 88 | sum = sum + ((temp) << (4*(length - i - 1))); 89 | } 90 | 91 | p = p + 1; 92 | } 93 | return sum; 94 | } 95 | 96 | 97 | int main(int argc, char *argv[]) 98 | { 99 | int fd, ret, i; 100 | char option; 101 | 102 | char wdata[20]; 103 | int write_len = 0; 104 | int read_len = 0; 105 | int ccc_cmd_id = -1; 106 | unsigned char device_addr = 0; 107 | unsigned char read_data[40]; 108 | char write_data[40]; 109 | char devpatch[30]; 110 | int smbus = 0; 111 | struct i2c_rdwr_ioctl_data i2c_rdwr_data; 112 | 113 | if(argc == 1) { 114 | usage(stdout, argc, argv); 115 | exit(EXIT_FAILURE); 116 | } 117 | 118 | while ((option = getopt_long(argc, argv, short_options, long_options, NULL)) != (char) -1) { 119 | // printf("option is c %c\n", option); 120 | switch (option) { 121 | case 'h': 122 | usage(stdout, argc, argv); 123 | exit(EXIT_SUCCESS); 124 | break; 125 | case 'd': 126 | memset(devpatch, 0, 30); 127 | strcpy(devpatch, optarg); 128 | break; 129 | case 'a': 130 | device_addr = atol(optarg); 131 | break; 132 | case 'c': 133 | ccc_cmd_id = StrToHex(optarg); 134 | break; 135 | 136 | case 'r': 137 | read_len = atol(optarg); 138 | break; 139 | case 'w': 140 | write_len = atol(optarg); 141 | printf("write_len %d \n", write_len); 142 | break; 143 | case 's': 144 | smbus = 1; 145 | break; 146 | default: 147 | usage(stdout, argc, argv); 148 | exit(EXIT_FAILURE); 149 | } 150 | } 151 | 152 | if(ccc_cmd_id) { 153 | printf("[%s] - ccc cmd id %d, read %d, write %d \n", devpatch, ccc_cmd_id, read_len, write_len); 154 | } else 155 | printf("[%s] - addr %x, read %d, write %d \n", devpatch, device_addr, read_len, write_len); 156 | 157 | fd= open(devpatch, O_RDWR); 158 | if(fd < 0) { 159 | perror("openerror"); 160 | exit(1); 161 | } 162 | 163 | i2c_rdwr_data.nmsgs = 2; 164 | 165 | i2c_rdwr_data.msgs= (struct i2c_msg *)malloc(i2c_rdwr_data.nmsgs * sizeof(struct i2c_msg)); 166 | 167 | if(i2c_rdwr_data.msgs == NULL) { 168 | perror("mallocerror"); 169 | exit(1); 170 | } 171 | 172 | i2c_rdwr_data.msgs[0].addr = device_addr; 173 | 174 | if(ccc_cmd_id != -1) { 175 | i2c_rdwr_data.msgs[0].len = write_len + 2; 176 | i2c_rdwr_data.msgs[0].flags = I3C_M_CCC; /* write */ 177 | i2c_rdwr_data.msgs[0].buf = (u8 *)write_data; 178 | i2c_rdwr_data.msgs[0].buf[0] = ccc_cmd_id; 179 | i2c_rdwr_data.msgs[0].buf[1] = 0; 180 | 181 | i2c_rdwr_data.nmsgs = 1; 182 | 183 | if(write_len) { 184 | i2c_rdwr_data.msgs[0].buf[1] = write_len; /* write length */ 185 | for(i = 0; i < write_len; i++) { 186 | printf("[%d] = ", i); 187 | scanf("%s", wdata); 188 | i2c_rdwr_data.msgs[0].buf[i + 2] = StrToHex(wdata); 189 | } 190 | // for(i = 0; i < write_len + 1; i++) 191 | // printf("%x ", i2c_rdwr_data.msgs[0].buf[i]); 192 | } 193 | 194 | if(read_len) { 195 | i2c_rdwr_data.msgs[0].len = read_len + 2; 196 | i2c_rdwr_data.msgs[0].flags = I3C_M_CCC | I2C_M_RD; /* read */ 197 | i2c_rdwr_data.msgs[0].buf[0] = ccc_cmd_id; 198 | i2c_rdwr_data.msgs[0].buf[1] = read_len; 199 | } 200 | 201 | if(!write_len && !write_len) { 202 | i2c_rdwr_data.nmsgs = 1; 203 | } 204 | 205 | ret= ioctl(fd, I2C_RDWR, (unsigned long)&i2c_rdwr_data); 206 | if(ret < 0) { 207 | perror("ccc cmd error"); 208 | exit(1); 209 | } 210 | 211 | 212 | printf("======== rx ==========================\n"); 213 | // for(i = 0; i < i2c_rdwr_data.msgs[0].buf[0]; i ++) 214 | // printf("%x \n", i2c_rdwr_data.msgs[0].buf[0]); 215 | printf("==================================\n"); 216 | } else if (smbus) { 217 | 218 | } else { 219 | printf("write xxx \n"); 220 | /*向e2prom的rdwr_addr地址寫入資料data*/ 221 | i2c_rdwr_data.nmsgs = 1; 222 | i2c_rdwr_data.msgs[0].len = 2; 223 | i2c_rdwr_data.msgs[0].addr= device_addr; 224 | i2c_rdwr_data.msgs[0].flags = 0; /* write */ 225 | i2c_rdwr_data.msgs[0].buf = write_data; 226 | i2c_rdwr_data.msgs[0].buf[0] = 0x50; /* write address */ 227 | i2c_rdwr_data.msgs[0].buf[1] = 0xaa; /* write data */ 228 | ret= ioctl(fd, I2C_RDWR, (unsigned long)&i2c_rdwr_data); 229 | if(ret < 0) { 230 | perror("writedata error"); 231 | exit(1); 232 | } 233 | } 234 | exit(1); 235 | #if 0 236 | printf("writedata: %d to address: %#x\n", data, rdwr_addr); 237 | data= 0; /* be zero*/ 238 | /*從e2prom的rdwr_addr地址讀取資料存入buf*/ 239 | i2c_rdwr_data.nmsgs= 2; 240 | i2c_rdwr_data.msgs[0].len= 1; 241 | i2c_rdwr_data.msgs[0].addr= device_addr; 242 | // i2c_rdwr_data.msgs[0].flags= 0; /* write */ 243 | i2c_rdwr_data.msgs[0].buf= &rdwr_addr; 244 | i2c_rdwr_data.msgs[1].len= 1; 245 | i2c_rdwr_data.msgs[1].addr= device_addr; 246 | i2c_rdwr_data.msgs[1].flags= 1; /* read */ 247 | i2c_rdwr_data.msgs[1].buf= &data; 248 | ret= ioctl(fd, I2C_RDWR, (unsigned long)&i2c_rdwr_data); 249 | if(ret < 0) { 250 | perror("readerror"); 251 | exit(1); 252 | } 253 | 254 | printf("read data: %d from address: %#x\n", data,rdwr_addr); 255 | #endif 256 | free(i2c_rdwr_data.msgs); 257 | close(fd); 258 | return 0; 259 | } 260 | -------------------------------------------------------------------------------- /i3c-test/i3c-test.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AspeedTech-BMC/aspeed_app/e74fc6e1fa56c16feb2fe32ccd6ca57c055684ef/i3c-test/i3c-test.o -------------------------------------------------------------------------------- /mctp-i3c/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CC = $(CROSS_COMPILE)gcc 8 | INCLUDE = . 9 | OBJS = 10 | LDLIBS = -lc -lrt -lgcc 11 | EXTRA_FLAGS = -lpthread 12 | CFLAGS += -Wall -O2 13 | EXEC_NAME = mctp-i3c 14 | 15 | all: $(EXEC_NAME) 16 | 17 | $(EXEC_NAME): $(EXEC_NAME).o 18 | $(CC) $(CFLAGS) $(OBJS) $(EXEC_NAME).o -o $@ $(LDLIBS) $(EXTRA_FLAGS) 19 | 20 | $(EXEC_NAME).o: $(OBJS) $(EXEC_NAME).c 21 | $(CC) $(CFLAGS) -l$(INCLUDE) -c $(EXEC_NAME).c 22 | 23 | clean: 24 | rm -f $(EXEC_NAME).elf $(EXEC_NAME).gdb $(EXEC_NAME).o $(EXEC_NAME) 25 | 26 | install: 27 | cp $(EXEC_NAME) $(INSTALL_DIR) 28 | -------------------------------------------------------------------------------- /mctp-socket/mctp-recv.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // 3 | // mctp-echo: MCTP echo server, for testing. 4 | // 5 | // Copyright (c) 2021 Code Construct 6 | // Copyright (c) 2021 Google 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "mctp.h" 17 | 18 | bool debug; 19 | bool skip; 20 | static const int DEFAULT_NET = 1; 21 | static const mctp_eid_t DEFAULT_EID = 8; 22 | static const size_t DEFAULT_LEN = 1; 23 | 24 | static void usage(void) 25 | { 26 | fprintf(stderr, "mctp-echo [type ] [skip 1] [debug 1]\n"); 27 | fprintf(stderr, "default eid %d net %d len %zd\n", 28 | DEFAULT_EID, DEFAULT_NET, DEFAULT_LEN); 29 | } 30 | 31 | int main(int argc, char **argv) 32 | { 33 | struct sockaddr_mctp addr; 34 | unsigned char *buf; 35 | socklen_t addrlen; 36 | size_t buflen; 37 | ssize_t len; 38 | char *endp, *optname, *optval; 39 | u8 type = 1; 40 | unsigned int tmp; 41 | int rc, sd; 42 | 43 | if (!(argc % 2)) { 44 | warnx("extra argument %s", argv[argc - 1]); 45 | usage(); 46 | return 255; 47 | } 48 | 49 | for (int i = 1; i < argc; i += 2) { 50 | optname = argv[i]; 51 | optval = argv[i + 1]; 52 | 53 | tmp = strtoul(optval, &endp, 0); 54 | 55 | if (!strcmp(optname, "debug")) { 56 | debug = true; 57 | } else if (!strcmp(optname, "skip")) { 58 | skip = true; 59 | } else if (!strcmp(optname, "type")) { 60 | if (tmp > 0xff) 61 | errx(EXIT_FAILURE, "Bad type"); 62 | type = tmp; 63 | } 64 | } 65 | sd = socket(AF_MCTP, SOCK_DGRAM, 0); 66 | if (sd < 0) 67 | err(EXIT_FAILURE, "socket"); 68 | 69 | memset(&addr, 0, sizeof(addr)); 70 | addr.smctp_family = AF_MCTP; 71 | addr.smctp_network = MCTP_NET_ANY; 72 | addr.smctp_addr.s_addr = MCTP_ADDR_ANY; 73 | addr.smctp_type = type; 74 | addr.smctp_tag = MCTP_TAG_OWNER; 75 | 76 | buflen = 0; 77 | buf = NULL; 78 | 79 | rc = bind(sd, (struct sockaddr *)&addr, sizeof(addr)); 80 | if (rc) 81 | err(EXIT_FAILURE, "bind"); 82 | 83 | for (;;) { 84 | len = recvfrom(sd, NULL, 0, MSG_PEEK | MSG_TRUNC, NULL, 0); 85 | if (len < 0) { 86 | warn("recvfrom(MSG_PEEK)"); 87 | continue; 88 | } 89 | 90 | if ((size_t)len > buflen) { 91 | buflen = len; 92 | buf = realloc(buf, buflen); 93 | if (!buf) 94 | err(EXIT_FAILURE, "realloc(%zd)", buflen); 95 | } 96 | 97 | addrlen = sizeof(addr); 98 | len = recvfrom(sd, buf, buflen, 0, 99 | (struct sockaddr *)&addr, &addrlen); 100 | if (len < 0) { 101 | warn("recvfrom"); 102 | continue; 103 | } 104 | 105 | if (addrlen != sizeof(addr)) { 106 | warnx("unknown address length %d, exp %zd", 107 | addrlen, sizeof(addr)); 108 | continue; 109 | } 110 | 111 | if (debug) { 112 | printf("recv: message from (net %d, eid %d), tag %d, type %d: len %zd", 113 | addr.smctp_network, addr.smctp_addr.s_addr, 114 | addr.smctp_tag, 115 | addr.smctp_type, 116 | len); 117 | 118 | printf("data:\n"); 119 | for (int i = 0; i < len; i++) 120 | printf("0x%02x ", buf[i]); 121 | printf("\n"); 122 | } 123 | 124 | // If has [skip 1], skip echo request message to requester. 125 | if (skip) 126 | continue; 127 | 128 | addr.smctp_tag &= ~MCTP_TAG_OWNER; 129 | 130 | rc = sendto(sd, buf, len, 0, 131 | (struct sockaddr *)&addr, sizeof(addr)); 132 | 133 | if (rc != (int)len) { 134 | warn("sendto"); 135 | continue; 136 | } 137 | } 138 | 139 | return EXIT_SUCCESS; 140 | } 141 | -------------------------------------------------------------------------------- /mctp-socket/mctp-req.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // 3 | // mctp-req: MCTP echo requester 4 | // 5 | // Copyright (c) 2021 Code Construct 6 | // Copyright (c) 2021 Google 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "mctp.h" 18 | #include "mctp-util.h" 19 | 20 | static const int DEFAULT_NET = 1; 21 | static const mctp_eid_t DEFAULT_EID = 8; 22 | static const size_t DEFAULT_LEN = 1; 23 | bool debug; 24 | bool skip; 25 | 26 | /* lladdrlen != -1 to ignore ifindex/lladdr */ 27 | static int mctp_req(unsigned int net, mctp_eid_t eid, 28 | unsigned int ifindex, u8 *lladdr, int lladdrlen, 29 | u8 type, u8 *data, size_t len) 30 | { 31 | struct sockaddr_mctp_ext addr; 32 | unsigned char *buf, *rxbuf; 33 | socklen_t addrlen; 34 | int rc, sd, val; 35 | size_t i; 36 | ssize_t ret; 37 | 38 | sd = socket(AF_MCTP, SOCK_DGRAM, 0); 39 | if (sd < 0) 40 | err(EXIT_FAILURE, "socket"); 41 | 42 | memset(&addr, 0x0, sizeof(addr)); 43 | addrlen = sizeof(struct sockaddr_mctp); 44 | addr.smctp_base.smctp_family = AF_MCTP; 45 | addr.smctp_base.smctp_network = net; 46 | addr.smctp_base.smctp_addr.s_addr = eid; 47 | addr.smctp_base.smctp_type = type; 48 | addr.smctp_base.smctp_tag = MCTP_TAG_OWNER; 49 | 50 | if (debug) { 51 | printf("req: sending to (net %d, eid %d), type %d, len %zu\n", 52 | net, eid, addr.smctp_base.smctp_type, len); 53 | } 54 | 55 | rxbuf = malloc(len); 56 | if (!rxbuf) 57 | err(EXIT_FAILURE, "malloc"); 58 | if (data) { 59 | buf = data; 60 | } else { 61 | buf = rxbuf; 62 | for (i = 0; i < len; i++) 63 | buf[i] = i & 0xff; 64 | } 65 | 66 | /* extended addressing */ 67 | if (lladdrlen != -1) { 68 | addrlen = sizeof(struct sockaddr_mctp_ext); 69 | addr.smctp_halen = lladdrlen; 70 | memcpy(addr.smctp_haddr, lladdr, lladdrlen); 71 | addr.smctp_ifindex = ifindex; 72 | printf(" ext ifindex %d ha[0]=0x%02x len %hhu\n", 73 | addr.smctp_ifindex, 74 | addr.smctp_haddr[0], addr.smctp_halen); 75 | val = 1; 76 | rc = setsockopt(sd, SOL_MCTP, MCTP_OPT_ADDR_EXT, &val, sizeof(val)); 77 | if (rc < 0) 78 | errx(EXIT_FAILURE, 79 | "Kernel does not support MCTP extended addressing"); 80 | } 81 | 82 | /* send data */ 83 | rc = sendto(sd, buf, len, 0, 84 | (struct sockaddr *)&addr, addrlen); 85 | if (rc != (int)len) 86 | err(EXIT_FAILURE, "sendto(%zd)", len); 87 | 88 | if (skip) { 89 | usleep(1); 90 | return 0; 91 | } 92 | 93 | ret = recvfrom(sd, NULL, 0, MSG_PEEK | MSG_TRUNC, NULL, 0); 94 | if (ret < 0) 95 | err(EXIT_FAILURE, "recvfrom"); 96 | len = (size_t)ret; 97 | 98 | rxbuf = realloc(rxbuf, len); 99 | if (!rxbuf) 100 | err(EXIT_FAILURE, "realloc"); 101 | 102 | /* receive response */ 103 | addrlen = sizeof(addr); 104 | rc = recvfrom(sd, rxbuf, len, MSG_TRUNC, 105 | (struct sockaddr *)&addr, &addrlen); 106 | if (rc < 0) 107 | err(EXIT_FAILURE, "recvfrom"); 108 | 109 | if (!(addrlen == sizeof(struct sockaddr_mctp_ext) || 110 | addrlen == sizeof(struct sockaddr_mctp))) 111 | errx(EXIT_FAILURE, "unknown recv address length %d, exp %zu or %zu)", 112 | addrlen, sizeof(struct sockaddr_mctp_ext), 113 | sizeof(struct sockaddr_mctp)); 114 | 115 | printf("req: message from (net %d, eid %d) type %d len %zd\n", 116 | addr.smctp_base.smctp_network, addr.smctp_base.smctp_addr.s_addr, 117 | addr.smctp_base.smctp_type, len); 118 | if (addrlen == sizeof(struct sockaddr_mctp_ext)) { 119 | printf(" ext ifindex %d ha[0]=0x%02x len %hhu\n", 120 | addr.smctp_ifindex, 121 | addr.smctp_haddr[0], addr.smctp_halen); 122 | } 123 | 124 | if (debug) { 125 | printf("data:\n"); 126 | for (i = 0; i < len; i++) 127 | printf("0x%02x ", rxbuf[i]); 128 | printf("\n"); 129 | } 130 | 131 | return 0; 132 | } 133 | 134 | static void usage(void) 135 | { 136 | fprintf(stderr, "mctp-req [eid ] [net ]"); 137 | fprintf(stderr, " [ifindex lladdr ] [type ] [len ]"); 138 | fprintf(stderr, " [data ] [skip 1] [debug 1]\n"); 139 | fprintf(stderr, "default eid %d net %d len %zd\n", 140 | DEFAULT_EID, DEFAULT_NET, DEFAULT_LEN); 141 | fprintf(stderr, "The data is in hex format separated by colon, e.g. 00:01:0f"); 142 | } 143 | 144 | int main(int argc, char **argv) 145 | { 146 | u8 *data, lladdr[MAX_ADDR_LEN]; 147 | int lladdrlen = -1, datalen = -1; 148 | unsigned int net = DEFAULT_NET; 149 | mctp_eid_t eid = DEFAULT_EID; 150 | size_t len = DEFAULT_LEN, sz; 151 | u8 type = 1; 152 | char *endp, *optname, *optval; 153 | unsigned int tmp, ifindex; 154 | bool valid_parse; 155 | int i; 156 | 157 | if (!(argc % 2)) { 158 | warnx("extra argument %s", argv[argc - 1]); 159 | usage(); 160 | return 255; 161 | } 162 | 163 | data = NULL; 164 | 165 | for (i = 1; i < argc; i += 2) { 166 | optname = argv[i]; 167 | optval = argv[i + 1]; 168 | 169 | tmp = strtoul(optval, &endp, 0); 170 | valid_parse = (endp != optval); 171 | 172 | if (!strcmp(optname, "eid")) { 173 | if (tmp > 0xff) 174 | errx(EXIT_FAILURE, "Bad eid"); 175 | eid = tmp; 176 | } else if (!strcmp(optname, "net")) { 177 | if (tmp > 0xff) 178 | errx(EXIT_FAILURE, "Bad net"); 179 | net = tmp; 180 | } else if (!strcmp(optname, "ifindex")) { 181 | ifindex = tmp; 182 | } else if (!strcmp(optname, "len")) { 183 | if (tmp > 64 * 1024) 184 | errx(EXIT_FAILURE, "Bad len"); 185 | len = tmp; 186 | } else if (!strcmp(optname, "type")) { 187 | if (tmp > 0xff) 188 | errx(EXIT_FAILURE, "Bad type"); 189 | type = tmp; 190 | } else if (!strcmp(optname, "data")) { 191 | sz = (strlen(optval) + 2) / 3; 192 | data = malloc(sz); 193 | if (!data) 194 | err(EXIT_FAILURE, "malloc"); 195 | if (parse_hex_addr(optval, data, &sz)) 196 | errx(EXIT_FAILURE, "Bad data"); 197 | 198 | datalen = sz; 199 | valid_parse = true; 200 | } else if (!strcmp(optname, "lladdr")) { 201 | sz = sizeof(lladdr); 202 | if (parse_hex_addr(optval, lladdr, &sz)) 203 | errx(EXIT_FAILURE, "Bad lladdr"); 204 | 205 | lladdrlen = sz; 206 | valid_parse = true; 207 | } else if (!strcmp(optname, "skip")) { 208 | skip = true; 209 | } else if (!strcmp(optname, "debug")) { 210 | debug = true; 211 | } else { 212 | errx(EXIT_FAILURE, "Unknown argument %s", optname); 213 | } 214 | 215 | // Handle bad integer etc. 216 | if (!valid_parse) { 217 | errx(EXIT_FAILURE, "invalid %s value %s", 218 | optname, optval); 219 | } 220 | } 221 | 222 | if (data) 223 | len = datalen; 224 | 225 | return mctp_req(net, eid, ifindex, lladdr, lladdrlen, type, data, len); 226 | } 227 | -------------------------------------------------------------------------------- /mctp-socket/mctp-util.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | // 3 | // mctp-echo: MCTP echo server, for testing. 4 | // 5 | // Copyright (c) 2021 Code Construct 6 | // Copyright (c) 2021 Google 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "mctp.h" 14 | #include "mctp-util.h" 15 | 16 | void mctp_hexdump(const void *b, int len, const char *indent) 17 | { 18 | const char *buf = b; 19 | const int row_len = 16; 20 | int i, j; 21 | 22 | for (i = 0; i < len; i += row_len) { 23 | char hbuf[row_len * strlen("00 ") + 1]; 24 | char cbuf[row_len + strlen("|") + 1]; 25 | 26 | for (j = 0; (j < row_len) && ((i + j) < len); j++) { 27 | unsigned char c = buf[i + j]; 28 | 29 | sprintf(hbuf + j * 3, "%02x ", c); 30 | 31 | if (!isprint(c)) 32 | c = '.'; 33 | 34 | sprintf(cbuf + j, "%c", c); 35 | } 36 | 37 | strcat(cbuf, "|"); 38 | 39 | printf("%s%08x %*s |%s\n", indent, i, 40 | (int)(0 - sizeof(hbuf) + 1), hbuf, cbuf); 41 | } 42 | } 43 | 44 | void print_hex_addr(const u8 *data, size_t len) 45 | { 46 | for (size_t i = 0; i < len; i++) { 47 | if (i > 0) 48 | putchar(':'); 49 | 50 | printf("%02x", data[i]); 51 | } 52 | } 53 | 54 | int write_hex_addr(const u8 *data, size_t len, char *dest, size_t dest_len) 55 | { 56 | size_t l; 57 | 58 | if (dest_len < len * 3) { 59 | snprintf(dest, dest_len, "XXXX"); 60 | return -EINVAL; 61 | } 62 | 63 | dest[0] = '\0'; 64 | for (size_t i = 0; i < len; i++) { 65 | if (i > 0) { 66 | l = snprintf(dest, dest_len, ":"); 67 | if (l >= dest_len) 68 | return -EPROTO; 69 | dest_len -= l; 70 | dest += l; 71 | } 72 | l = snprintf(dest, dest_len, "%02x", data[i]); 73 | if (l >= dest_len) 74 | return -EPROTO; 75 | dest_len -= l; 76 | dest += l; 77 | } 78 | return 0; 79 | } 80 | 81 | // Accepts colon separated hex bytes 82 | int parse_hex_addr(const char *in, u8 *out, size_t *out_len) 83 | { 84 | int rc = -1; 85 | size_t out_pos = 0; 86 | 87 | while (1) { 88 | if (*in == '\0') { 89 | rc = 0; 90 | break; 91 | } else if (*in == ':') { 92 | in++; 93 | if (*in == ':' || *in == '\0' || out_pos == 0) { 94 | // can't have repeated ':' or ':' at start or end. 95 | break; 96 | } 97 | } else { 98 | char *endp; 99 | int tmp; 100 | 101 | tmp = strtoul(in, &endp, 16); 102 | if (endp == in || tmp > 0xff) 103 | break; 104 | 105 | if (out_pos >= *out_len) 106 | break; 107 | 108 | *out = tmp & 0xff; 109 | out++; 110 | out_pos++; 111 | in = endp; 112 | } 113 | } 114 | 115 | if (rc) 116 | *out_len = 0; 117 | else 118 | *out_len = out_pos; 119 | 120 | return rc; 121 | } 122 | 123 | int parse_uint32(const char *str, u32 *out) 124 | { 125 | unsigned long v; 126 | char *endp; 127 | 128 | v = strtoul(str, &endp, 0); 129 | if (endp == str || *endp != '\0') 130 | return -EINVAL; 131 | if (v > UINT32_MAX) 132 | return -EOVERFLOW; 133 | *out = v; 134 | return 0; 135 | } 136 | 137 | int parse_int32(const char *str, s32 *out) 138 | { 139 | long v; 140 | char *endp; 141 | 142 | v = strtol(str, &endp, 0); 143 | if (endp == str || *endp != '\0') 144 | return -EINVAL; 145 | if (v > INT32_MAX || v < INT32_MIN) 146 | return -EOVERFLOW; 147 | *out = v; 148 | return 0; 149 | } 150 | 151 | /* Returns a malloced pointer */ 152 | char *bytes_to_uuid(const u8 u[16]) 153 | { 154 | char *buf = malloc(37); 155 | 156 | if (!buf) 157 | return NULL; 158 | 159 | snprintf(buf, 37, 160 | "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 161 | u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], 162 | u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]); 163 | return buf; 164 | } 165 | -------------------------------------------------------------------------------- /mctp-socket/mctp-util.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | // 3 | // mctp-echo: MCTP echo server, for testing. 4 | // 5 | // Copyright (c) 2021 Code Construct 6 | // Copyright (c) 2021 Google 7 | 8 | #include 9 | #include 10 | #include "mctp.h" 11 | 12 | void mctp_hexdump(const void *b, int len, const char *indent); 13 | void print_hex_addr(const u8 *data, size_t len); 14 | int write_hex_addr(const u8 *data, size_t len, char *dest, size_t dest_len); 15 | int parse_hex_addr(const char *in, u8 *out, size_t *out_len); 16 | int parse_uint32(const char *str, u32 *out); 17 | int parse_int32(const char *str, s32 *out); 18 | /* Returns a malloced pointer */ 19 | char *bytes_to_uuid(const u8 u[16]); 20 | -------------------------------------------------------------------------------- /mctp-socket/mctp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | // 3 | // mctp: userspace utility for managing the kernel MCTP stack. 4 | // 5 | // Interim definitions for the MCTP kernel interface. While the MCTP kernel 6 | // API is going through upstream, system toolchains may not yet have the 7 | // required definitions for mctp tools. This header provides fallback 8 | // implementations (protected by #ifdef guards) of those new interfaces. 9 | // 10 | // Copyright (c) 2021 Code Construct 11 | // Copyright (c) 2021 Google 12 | 13 | #ifndef _MCTP_H 14 | #define _MCTP_H 15 | 16 | #if HAVE_LINUX_MCTP_H 17 | #include 18 | #endif 19 | #include 20 | #include 21 | 22 | #ifndef AF_MCTP 23 | #define AF_MCTP 45 24 | #endif 25 | 26 | /* MCTP serial line discipline */ 27 | #ifndef N_MCTP 28 | #define N_MCTP 28 29 | #endif 30 | 31 | #include 32 | 33 | typedef unsigned char u8; 34 | typedef signed char s8; 35 | 36 | typedef unsigned long u32; 37 | typedef long s32; 38 | 39 | typedef unsigned short int u16; 40 | typedef signed short int s16; 41 | 42 | #ifndef MCTP_NET_ANY 43 | 44 | typedef u8 mctp_eid_t; 45 | 46 | struct mctp_addr { 47 | mctp_eid_t s_addr; 48 | }; 49 | 50 | struct sockaddr_mctp { 51 | unsigned short int smctp_family; 52 | unsigned short __smctp_pad0; 53 | int smctp_network; 54 | struct mctp_addr smctp_addr; 55 | u8 smctp_type; 56 | u8 smctp_tag; 57 | u8 __smctp_pad1; 58 | }; 59 | 60 | #define MCTP_NET_ANY 0 61 | #define MCTP_ADDR_ANY 0xff 62 | #define MCTP_TAG_OWNER 0x08 63 | 64 | #endif /* MCTP_NET_ANY */ 65 | 66 | #ifndef MAX_ADDR_LEN 67 | #define MAX_ADDR_LEN 32 68 | #endif 69 | 70 | /* Added in v5.16 */ 71 | #ifndef MCTP_OPT_ADDR_EXT 72 | 73 | #define MCTP_OPT_ADDR_EXT 1 74 | 75 | struct sockaddr_mctp_ext { 76 | struct sockaddr_mctp smctp_base; 77 | int smctp_ifindex; 78 | u8 smctp_halen; 79 | u8 __smctp_pad0[3]; 80 | unsigned char smctp_haddr[MAX_ADDR_LEN]; 81 | }; 82 | 83 | #endif /* MCTP_OPT_ADDR_EXT */ 84 | 85 | #ifndef IFLA_MCTP_MAX 86 | 87 | /* From if_link.h */ 88 | enum { 89 | IFLA_MCTP_UNSPEC, 90 | IFLA_MCTP_NET, 91 | __IFLA_MCTP_MAX, 92 | }; 93 | 94 | #define IFLA_MCTP_MAX (__IFLA_MCTP_MAX - 1) 95 | 96 | #endif /* IFLA_MCTP_MAX */ 97 | 98 | /* setsockopt(2) options */ 99 | #ifndef SOL_MCTP 100 | #define SOL_MCTP 285 101 | #endif 102 | 103 | #ifndef RTNLGRP_MCTP_IFADDR 104 | #define RTNLGRP_MCTP_IFADDR 34 105 | #endif 106 | 107 | #endif /* _MCTP_H */ 108 | -------------------------------------------------------------------------------- /mctp-socket/meson.build: -------------------------------------------------------------------------------- 1 | project('mctp-socket-based-utilities', 'c', 'cpp', 2 | version : '1.0', 3 | meson_version: '>=0.57.0', 4 | default_options: [ 5 | 'werror=true', 6 | ]) 7 | 8 | # Generate the aspeed-pfr-tool executable 9 | executable( 10 | 'mctp-skt-req', 11 | [ 12 | 'mctp-req.c', 13 | 'mctp-util.c' 14 | ], 15 | install: true 16 | ) 17 | 18 | executable( 19 | 'mctp-skt-recv', 20 | [ 21 | 'mctp-recv.c' 22 | ], 23 | install: true 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /mctp/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CFLAGS += -Wall -O2 8 | LIBS = -ldl 9 | OBJS = libmctp.o mctp.o 10 | EXE = mctp-ast 11 | CC = $(CROSS_COMPILE)gcc 12 | 13 | $(EXE): $(OBJS) 14 | $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) 15 | 16 | %.o:%.c 17 | $(CC) $(CFLAGS) -c $< -o $@ 18 | 19 | clean: 20 | rm -f $(EXE) $(OBJS) 21 | 22 | install: 23 | cp $(EXE) $(INSTALL_DIR) 24 | 25 | -------------------------------------------------------------------------------- /mctp/libmctp.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0+ 2 | /* 3 | * Copyright 2021 Aspeed Technology Inc. 4 | */ 5 | #include "libmctp.h" 6 | 7 | void mctp_swap_pcie_vdm_hdr(struct aspeed_mctp_xfer *xfer) 8 | { 9 | int i; 10 | 11 | for (i = 0; i < 4; i++) 12 | xfer->header[i] = htobe32(xfer->header[i]); 13 | } 14 | 15 | struct mctp_binding_astpcie *aspeed_mctp_init(char *dev) 16 | { 17 | struct mctp_binding_astpcie *astpcie; 18 | 19 | astpcie = malloc(sizeof(struct mctp_binding_astpcie)); 20 | 21 | astpcie->fd = open(dev, O_RDWR, 0); 22 | if (astpcie->fd == -1) 23 | return NULL; 24 | /* close on exec */ 25 | if (fcntl(astpcie->fd, F_SETFD, 1) == -1) { 26 | close(astpcie->fd); 27 | astpcie->fd = -1; 28 | return NULL; 29 | } 30 | return astpcie; 31 | } 32 | 33 | void aspeed_mctp_free(struct mctp_binding_astpcie *astpcie) 34 | { 35 | close(astpcie->fd); 36 | } 37 | 38 | static int aspeed_mctp_poll(struct mctp_binding_astpcie *astpcie, int timeout) 39 | { 40 | struct pollfd fds[1]; 41 | int rc; 42 | 43 | fds[0].fd = astpcie->fd; 44 | fds[0].events = POLLIN | POLLOUT; 45 | 46 | rc = poll(fds, 1, timeout); 47 | 48 | if (rc > 0) 49 | return fds[0].revents; 50 | 51 | if (rc < 0) { 52 | perror("Poll returned error status"); 53 | 54 | return -1; 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | int aspeed_mctp_recv(struct mctp_binding_astpcie *astpcie, 61 | struct aspeed_mctp_xfer *xfer) 62 | { 63 | int ret; 64 | 65 | ret = read(astpcie->fd, xfer->header, ASPEED_MCTP_XFER_SIZE); 66 | if (ret < 0) { 67 | MCTP_DBUG("err\n"); 68 | perror("MCTP read error!\n"); 69 | } 70 | return ret; 71 | } 72 | 73 | int aspeed_mctp_send(struct mctp_binding_astpcie *astpcie, 74 | struct aspeed_mctp_xfer *xfer) 75 | { 76 | int ret; 77 | 78 | ret = write(astpcie->fd, xfer->header, 79 | xfer->buf_len + ASPEED_MCTP_PCIE_VDM_HDR_SIZE); 80 | if (ret < 0) { 81 | perror("MCTP write error!\n"); 82 | return ret; 83 | } 84 | return ret; 85 | } 86 | 87 | void wait_for_message(struct mctp_binding_astpcie *astpcie) 88 | { 89 | int rc; 90 | bool received = false; 91 | 92 | while (!received) { 93 | rc = aspeed_mctp_poll(astpcie, 1000); 94 | if (rc & POLLIN) 95 | received = true; 96 | } 97 | } 98 | 99 | void wait_for_xfer_done(struct mctp_binding_astpcie *astpcie) 100 | { 101 | int rc; 102 | bool xfered = false; 103 | 104 | while (!xfered) { 105 | rc = aspeed_mctp_poll(astpcie, 1000); 106 | if (rc & POLLOUT) 107 | xfered = true; 108 | } 109 | } 110 | 111 | int aspeed_mctp_register_default_handler(struct mctp_binding_astpcie *astpcie) 112 | { 113 | return ioctl(astpcie->fd, ASPEED_MCTP_IOCTL_REGISTER_DEFAULT_HANDLER); 114 | } 115 | 116 | int aspeed_mctp_get_mtu(struct mctp_binding_astpcie *astpcie) 117 | { 118 | struct aspeed_mctp_get_mtu get_mtu; 119 | int rc; 120 | 121 | rc = ioctl(astpcie->fd, ASPEED_MCTP_IOCTL_GET_MTU, 122 | &get_mtu); 123 | if (!rc) 124 | astpcie->mtu = get_mtu.mtu; 125 | printf("astpcie->mtu = %d\n", astpcie->mtu); 126 | 127 | return rc; 128 | } 129 | -------------------------------------------------------------------------------- /mctp/libmctp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ */ 2 | /* 3 | * Copyright (c) 2020 Intel Corporation 4 | * Copyright 2021 Aspeed Technology Inc. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | /*************************************************************************************/ 22 | #define ASPEED_MCTP_XFER_SIZE 4096 23 | 24 | /* 25 | * MCTP operations 26 | * @ASPEED_MCTP_IOCTL_FILTER_EID: enable/disable filter incoming packets based 27 | * on Endpoint ID (BROKEN) 28 | * @ASPEED_MCTP_IOCTL_GET_BDF: read PCI bus/device/function of MCTP Controller 29 | * @ASPEED_MCTP_IOCTL_GET_MEDIUM_ID: read MCTP physical medium identifier 30 | * related to PCIe revision 31 | * @ASPEED_MCTP_IOCTL_GET_MTU: read max transmission unit (in bytes) 32 | * @ASPEED_MCTP_IOCTL_REGISTER_DEFAULT_HANDLER Register client as default 33 | * handler that receives all MCTP messages that were not dispatched to other 34 | * clients 35 | * @ASPEED_MCTP_IOCTL_REGISTER_TYPE_HANDLER Register client to receive all 36 | * messages of specified MCTP type or PCI vendor defined type 37 | * @ASPEED_MCTP_IOCTL_UNREGISTER_TYPE_HANDLER Unregister client as handler 38 | * for specified MCTP type or PCI vendor defined message type 39 | * @ASPEED_MCTP_GET_EID_INFO: read list of existing endpoint mappings 40 | * returns count which is less of the two requested count and existing count 41 | * @ASPEED_MCTP_SET_EID_INFO: write list of endpoint mappings 42 | * overwrites already existing endpoint mappings 43 | */ 44 | 45 | struct aspeed_mctp_filter_eid { 46 | __u8 eid; 47 | bool enable; 48 | }; 49 | 50 | struct aspeed_mctp_get_bdf { 51 | __u16 bdf; 52 | }; 53 | 54 | struct aspeed_mctp_get_medium_id { 55 | __u8 medium_id; 56 | }; 57 | 58 | struct aspeed_mctp_get_mtu { 59 | __u16 mtu; 60 | }; 61 | 62 | struct aspeed_mctp_type_handler_ioctl { 63 | __u8 mctp_type; /* MCTP message type as per DSP239*/ 64 | /* Below params must be 0 if mctp_type is not Vendor Defined PCI */ 65 | __u16 pci_vendor_id; /* PCI Vendor ID */ 66 | __u16 vendor_type; /* Vendor specific type */ 67 | __u16 vendor_type_mask; /* Mask applied to vendor type */ 68 | }; 69 | 70 | struct aspeed_mctp_eid_info { 71 | __u8 eid; 72 | __u16 bdf; 73 | }; 74 | 75 | struct aspeed_mctp_get_eid_info { 76 | __u64 ptr; 77 | __u16 count; 78 | __u8 start_eid; 79 | }; 80 | 81 | struct aspeed_mctp_set_eid_info { 82 | __u64 ptr; 83 | __u16 count; 84 | }; 85 | 86 | #define ASPEED_MCTP_IOCTL_BASE 0x4d 87 | 88 | #define ASPEED_MCTP_IOCTL_FILTER_EID \ 89 | _IOW(ASPEED_MCTP_IOCTL_BASE, 0, struct aspeed_mctp_filter_eid) 90 | #define ASPEED_MCTP_IOCTL_GET_BDF \ 91 | _IOR(ASPEED_MCTP_IOCTL_BASE, 1, struct aspeed_mctp_get_bdf) 92 | #define ASPEED_MCTP_IOCTL_GET_MEDIUM_ID \ 93 | _IOR(ASPEED_MCTP_IOCTL_BASE, 2, struct aspeed_mctp_get_medium_id) 94 | #define ASPEED_MCTP_IOCTL_GET_MTU \ 95 | _IOR(ASPEED_MCTP_IOCTL_BASE, 3, struct aspeed_mctp_get_mtu) 96 | #define ASPEED_MCTP_IOCTL_REGISTER_DEFAULT_HANDLER \ 97 | _IO(ASPEED_MCTP_IOCTL_BASE, 4) 98 | #define ASPEED_MCTP_IOCTL_REGISTER_TYPE_HANDLER \ 99 | _IOW(ASPEED_MCTP_IOCTL_BASE, 6, struct aspeed_mctp_type_handler_ioctl) 100 | #define ASPEED_MCTP_IOCTL_UNREGISTER_TYPE_HANDLER \ 101 | _IOW(ASPEED_MCTP_IOCTL_BASE, 7, struct aspeed_mctp_type_handler_ioctl) 102 | #define ASPEED_MCTP_IOCTL_GET_EID_INFO \ 103 | _IOWR(ASPEED_MCTP_IOCTL_BASE, 8, struct aspeed_mctp_get_eid_info) 104 | #define ASPEED_MCTP_IOCTL_SET_EID_INFO \ 105 | _IOW(ASPEED_MCTP_IOCTL_BASE, 9, struct aspeed_mctp_set_eid_info) 106 | 107 | #define ASPEED_MCTP_PCIE_VDM_HDR_SIZE 16 108 | #define ASPEED_MCTP_PCIE_VDM_HDR_SIZE_DW 4 109 | 110 | #define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) 111 | #define ALIGN(x, a) ALIGN_MASK(x, (a)-1) 112 | 113 | #define ASPEED_MCTP_DEBUG 114 | 115 | #ifdef ASPEED_MCTP_DEBUG 116 | #define MCTP_DBUG(fmt, args...) printf("%s() " fmt, __func__, ##args) 117 | #else 118 | #define MCTP_DBUG(fmt, args...) 119 | #endif 120 | 121 | /*************************************************************************************/ 122 | struct pcie_vdm_header { 123 | __u32 length: 10, 124 | revd0: 2, 125 | attr: 2, 126 | ep: 1, 127 | td: 1, 128 | revd1: 4, 129 | tc: 3, 130 | revd2: 1, 131 | type_routing: 5, 132 | fmt: 2, 133 | revd3: 1; 134 | __u8 message_code; 135 | __u8 vdm_code: 4, 136 | pad_len: 2, 137 | tag_revd: 2; 138 | __u16 pcie_req_id; 139 | __u16 vender_id; 140 | __u16 pcie_target_id; 141 | __u8 msg_tag: 3, 142 | to: 1, 143 | pkt_seq: 2, 144 | eom: 1, 145 | som: 1; 146 | __u8 src_epid; 147 | __u8 dest_epid; 148 | __u8 header_ver: 4, 149 | rsvd: 4; 150 | }; 151 | 152 | struct aspeed_mctp_xfer { 153 | unsigned int *header; 154 | unsigned char *xfer_buff; 155 | unsigned int buf_len; 156 | }; 157 | 158 | struct mctp_binding_astpcie { 159 | int fd; 160 | __u16 mtu; 161 | }; 162 | 163 | void mctp_swap_pcie_vdm_hdr(struct aspeed_mctp_xfer *data); 164 | void wait_for_message(struct mctp_binding_astpcie *astpcie); 165 | void wait_for_xfer_done(struct mctp_binding_astpcie *astpcie); 166 | struct mctp_binding_astpcie *aspeed_mctp_init(char *dev); 167 | void aspeed_mctp_free(struct mctp_binding_astpcie *astpcie); 168 | int aspeed_mctp_send(struct mctp_binding_astpcie *astpcie, 169 | struct aspeed_mctp_xfer *xfer); 170 | int aspeed_mctp_recv(struct mctp_binding_astpcie *astpcie, 171 | struct aspeed_mctp_xfer *xfer); 172 | int aspeed_mctp_register_default_handler(struct mctp_binding_astpcie *astpcie); 173 | int aspeed_mctp_get_mtu(struct mctp_binding_astpcie *astpcie); 174 | -------------------------------------------------------------------------------- /mctp/mctp.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0+ 2 | /* 3 | * Copyright 2021 Aspeed Technology Inc. 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "libmctp.h" 19 | 20 | static void usage(FILE *fp, int argc, char **argv) 21 | { 22 | fprintf(fp, 23 | "Usage: %s [options]\n\n" 24 | "Options:\n" 25 | " -h | --help Print this message\n" 26 | " -n | --node mctp device node\n" 27 | " -t | --xfer mctp xfer\n" 28 | " -r | --recv mctp recv\n" 29 | " -i | --dest_id destination endpoint ID\n" 30 | " -b | --bus destination pcie bus number\n" 31 | " -d | --dev destination pcie dev number\n" 32 | " -f | --fun destination pcie fun number\n" 33 | " -o | --routing pcie routing type 0: route to RC, 2: route by ID, 3: Broadcase from RC\n" 34 | " -l | --length bytes length >= 64\n" 35 | " -c | --continue continue (0: loop, n: count number)\n" 36 | " -s | --som set som\n" 37 | " -e | --eom set eom\n" 38 | " example:\n" 39 | " tx : mctp -n /dev/aspeed-mctp -t -b 7 -d 0 -f 0 -o 2 -l 1024\n" 40 | " rx : mctp -n /dev/aspeed-mctp -r\n" 41 | "", 42 | argv[0]); 43 | } 44 | 45 | static const char short_options[] = "htri:b:d:f:o:l:c:s:e:n:"; 46 | 47 | static const struct option long_options[] = { 48 | { "help", no_argument, NULL, 'h' }, 49 | { "xfer", no_argument, NULL, 't' }, 50 | { "recv", no_argument, NULL, 'r' }, 51 | { "id", required_argument, NULL, 'i' }, 52 | { "bus", required_argument, NULL, 'b' }, 53 | { "dev", required_argument, NULL, 'd' }, 54 | { "fun", required_argument, NULL, 'f' }, 55 | { "routing", required_argument, NULL, 'o' }, 56 | { "length", required_argument, NULL, 'l' }, 57 | { "som", required_argument, NULL, 's' }, 58 | { "eom", required_argument, NULL, 'e' }, 59 | { "node", required_argument, NULL, 'n' }, 60 | { "continue", required_argument, NULL, 'c' }, 61 | { 0, 0, 0, 0 } 62 | }; 63 | 64 | void tx_debug(__u8 *mctp_header, __u8 *xfer_buff, __u16 length) 65 | { 66 | __u32 i; 67 | 68 | printf("mctp header --\n"); 69 | for (i = 0; i < 16; i++) 70 | printf("%02x ", mctp_header[i]); 71 | 72 | printf("\n"); 73 | printf("mctp buff --\n"); 74 | printf("----- TX PADLOAD - HEADER ----\n"); 75 | for (i = 0; i < 16; i++) 76 | printf("%02x ", xfer_buff[i]); 77 | printf("\n"); 78 | 79 | printf("----- PADLOAD - DATA ----\n"); 80 | for (i = 16; i < length; i++) { 81 | if (i % 16 == 0) 82 | printf("\n"); 83 | printf("%02x ", xfer_buff[i]); 84 | } 85 | 86 | printf("\n"); 87 | } 88 | 89 | int aspeed_mctp_tx(struct mctp_binding_astpcie *astpcie, int length, int bus, 90 | int dev, int fun, int eid, int routing, int som, int eom) 91 | { 92 | struct aspeed_mctp_xfer xfer; 93 | struct pcie_vdm_header *header; 94 | unsigned char *mctp_header; 95 | unsigned int remain_xfer; 96 | unsigned char pattern = 0; 97 | unsigned char sed = 0; 98 | int ret = 0; 99 | int i, xfer_index; 100 | int debug = 1; 101 | 102 | remain_xfer = length; 103 | pattern = rand(); 104 | sed = 0x01; 105 | 106 | memset(&xfer, 0, sizeof(struct aspeed_mctp_xfer)); 107 | xfer.header = malloc(astpcie->mtu + ASPEED_MCTP_PCIE_VDM_HDR_SIZE); 108 | xfer.xfer_buff = (unsigned char *)(xfer.header + 109 | ASPEED_MCTP_PCIE_VDM_HDR_SIZE_DW); 110 | 111 | header = (struct pcie_vdm_header *)xfer.header; 112 | mctp_header = (unsigned char *)xfer.header; 113 | //prepare default vdm header 114 | header->attr = 0x1; 115 | header->ep = 0x0; 116 | header->td = 0x0; 117 | header->tc = 0x0; 118 | header->type_routing = 0x10 | (routing & 0x7); 119 | header->fmt = 0x3; 120 | header->message_code = 0x7f; 121 | header->vdm_code = 0x0; 122 | 123 | header->vender_id = 0x1ab4; 124 | 125 | header->pcie_target_id = 126 | ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | ((fun & 0x7)); 127 | 128 | header->msg_tag = 0; 129 | header->to = 0; 130 | header->pkt_seq = 0; 131 | header->som = som; 132 | header->src_epid = 0; 133 | header->dest_epid = eid & 0xff; 134 | header->header_ver = 0x1; 135 | /* 0 ~ 13 : fix header, 14: sed, 15 : pattern, data pad load */ 136 | //generate data 137 | xfer.xfer_buff[0] = 0x1; 138 | xfer.xfer_buff[1] = 0x2; 139 | xfer.xfer_buff[2] = 0x3; 140 | xfer.xfer_buff[3] = 0x4; 141 | 142 | //header pattern; 143 | for (i = 4; i < 10; i++) { 144 | xfer.xfer_buff[i] = 0x5a; 145 | } 146 | 147 | xfer.xfer_buff[10] = 0; 148 | xfer.xfer_buff[11] = 0; 149 | xfer.xfer_buff[12] = 0; 150 | xfer.xfer_buff[13] = 0; 151 | xfer.xfer_buff[14] = sed; 152 | xfer.xfer_buff[15] = pattern; 153 | 154 | if (debug) 155 | printf("mctp_tx pattern : 0x%02x\n sed : 0x%02x\n len : 0x%02x\n", 156 | xfer.xfer_buff[15], xfer.xfer_buff[14], 157 | xfer.xfer_buff[13]); 158 | 159 | while (remain_xfer > astpcie->mtu) { 160 | header->length = astpcie->mtu >> 2; 161 | header->pad_len = 0; 162 | header->eom = 0; 163 | xfer_index = header->som ? 17 : 1; 164 | xfer.xfer_buff[xfer_index - 1] = (pattern + sed) % 0xff; 165 | for (; xfer_index < astpcie->mtu; xfer_index++) 166 | xfer.xfer_buff[xfer_index] = 167 | (xfer.xfer_buff[xfer_index - 1] + sed) % 0xff; 168 | if (debug) 169 | tx_debug(mctp_header, xfer.xfer_buff, astpcie->mtu); 170 | /* letobe */ 171 | mctp_swap_pcie_vdm_hdr(&xfer); 172 | xfer.buf_len = ALIGN(astpcie->mtu, 4); 173 | ret = aspeed_mctp_send(astpcie, &xfer); 174 | remain_xfer -= astpcie->mtu; 175 | pattern = xfer.xfer_buff[astpcie->mtu - 1] % 0xff; 176 | mctp_swap_pcie_vdm_hdr(&xfer); 177 | header->som = 0; 178 | header->pkt_seq += 1; 179 | } 180 | 181 | if (remain_xfer) { 182 | header->length = ALIGN(remain_xfer, 4) >> 2; 183 | header->pad_len = ALIGN(remain_xfer, 4) - remain_xfer; 184 | header->eom = eom; 185 | xfer_index = header->som ? 17 : 1; 186 | xfer.xfer_buff[xfer_index - 1] = (pattern + sed) % 0xff; 187 | for (; xfer_index < remain_xfer; xfer_index++) 188 | xfer.xfer_buff[xfer_index] = 189 | (xfer.xfer_buff[xfer_index - 1] + sed) % 0xff; 190 | if (debug) 191 | tx_debug(mctp_header, xfer.xfer_buff, remain_xfer); 192 | /* letobe */ 193 | mctp_swap_pcie_vdm_hdr(&xfer); 194 | xfer.buf_len = ALIGN(remain_xfer, 4); 195 | ret = aspeed_mctp_send(astpcie, &xfer); 196 | } 197 | 198 | free(xfer.header); 199 | 200 | if (ret < 0) 201 | return 1; 202 | else 203 | return 0; 204 | } 205 | 206 | int aspeed_mctp_rx(struct mctp_binding_astpcie *astpcie, 207 | struct aspeed_mctp_xfer *xfer) 208 | { 209 | struct pcie_vdm_header *header = (struct pcie_vdm_header *)xfer->header; 210 | unsigned char *vmd_header; 211 | int recv_length; 212 | unsigned char sed = 0; 213 | unsigned char pattern = 0; 214 | int i; 215 | int ret; 216 | int cmp_err = 0; 217 | int mctp_seq_num = 0; 218 | int mctp_tag = 0; 219 | int debug = 1; 220 | // 221 | next_mctp: 222 | header->length = 0; 223 | vmd_header = (unsigned char *)xfer->header; 224 | memset(header, 0, sizeof(struct pcie_vdm_header)); 225 | wait_for_message(astpcie); 226 | ret = aspeed_mctp_recv(astpcie, xfer); 227 | if (ret < 0) 228 | return ret; 229 | /* betole */ 230 | mctp_swap_pcie_vdm_hdr(xfer); 231 | 232 | if (!header->length) 233 | return -1; 234 | 235 | if (debug) 236 | printf("MCTP Header :som [%d], eom [%d], tag [%d], seq [%d]\n", 237 | header->som, header->eom, header->msg_tag, 238 | header->pkt_seq); 239 | 240 | if (header->som) { 241 | mctp_tag = header->msg_tag; 242 | mctp_seq_num = header->pkt_seq; 243 | if (!header->eom) { 244 | mctp_seq_num++; 245 | mctp_seq_num &= 0x3; 246 | } 247 | } else { 248 | if (mctp_tag != header->msg_tag) { 249 | printf("mctp tag error "); 250 | cmp_err = 1; 251 | return 1; 252 | } 253 | if (mctp_seq_num != header->pkt_seq) { 254 | printf("mctp seq error mctp_seq_num %d , header->pkt_seq %d\n", 255 | mctp_seq_num, header->pkt_seq); 256 | cmp_err = 1; 257 | return 1; 258 | } else { 259 | mctp_seq_num++; 260 | mctp_seq_num &= 0x3; 261 | } 262 | } 263 | 264 | if (debug) { 265 | for (i = 0; i < 16; i++) 266 | printf("%02x ", vmd_header[i]); 267 | 268 | printf("\n=========================================\n"); 269 | } 270 | 271 | recv_length = (header->length * 4) - header->pad_len; 272 | 273 | if (!header->som) 274 | goto padload_dump; 275 | 276 | if (xfer->xfer_buff[0] != 0x1 || xfer->xfer_buff[1] != 0x2 || 277 | xfer->xfer_buff[2] != 0x3 || xfer->xfer_buff[3] != 0x4) 278 | cmp_err = 1; 279 | 280 | for (i = 4; i < 10; i++) 281 | if (xfer->xfer_buff[i] != 0x5a) 282 | cmp_err = 1; 283 | 284 | for (i = 10; i < 12; i++) 285 | if (xfer->xfer_buff[i] != 0x0) 286 | cmp_err = 1; 287 | 288 | if (cmp_err) 289 | printf("\nPadload HEADER Error !!\n"); 290 | 291 | sed = xfer->xfer_buff[14]; 292 | pattern = xfer->xfer_buff[15]; 293 | 294 | if (xfer->xfer_buff[16] != (pattern + sed) % 0xff) 295 | return 1; 296 | 297 | if (debug) 298 | printf("----- RX PADLOAD len [%d] - HEADER ----\n", 299 | recv_length); 300 | 301 | padload_dump: 302 | 303 | if (debug) { 304 | printf("\n"); 305 | for (i = 0; i < 16; i++) { 306 | printf("%02x ", xfer->xfer_buff[i]); 307 | } 308 | 309 | if (header->som) 310 | printf("\n----- PADLOAD - DATA ---- "); 311 | } 312 | 313 | for (i = 16; i < recv_length; i++) { 314 | if (header->som) { 315 | if (xfer->xfer_buff[i] != 316 | ((xfer->xfer_buff[i - 1] + sed) % 0xff)) { 317 | //printf("CMP Error idx %d : !! %x != %x \n", i, xfer->xfer_buff[i], (xfer->xfer_buff[i - 1] + sed) % 0xff); 318 | cmp_err = 1; 319 | } 320 | } 321 | if (debug) { 322 | if (i % 16 == 0) 323 | printf("\n"); 324 | 325 | printf("%02x ", xfer->xfer_buff[i]); 326 | } 327 | } 328 | 329 | if (debug) 330 | printf("\n"); 331 | 332 | if (!header->eom) 333 | goto next_mctp; 334 | 335 | if (cmp_err == 1) 336 | return 1; 337 | 338 | return 0; 339 | } 340 | 341 | int main(int argc, char *argv[]) 342 | { 343 | char dev_name[100] = "/dev/aspeed-mctp0"; 344 | int xfer_dir = 0; 345 | int cont = 1; 346 | int times = 0; 347 | int length = 0; 348 | int ret; 349 | int som = 1; 350 | int eom = 1; 351 | int BUS = 0; 352 | int DEV = 0; 353 | int FUN = 0; 354 | int EID = 0; 355 | int routing = 2; 356 | char option; 357 | int infinity_loop = 0; 358 | int rx_flag = 0; 359 | struct mctp_binding_astpcie *astpcie; 360 | struct aspeed_mctp_xfer mctp_xfer; 361 | 362 | if (!argv[1]) { 363 | usage(stdout, argc, argv); 364 | exit(EXIT_FAILURE); 365 | } 366 | 367 | while ((option = getopt_long(argc, argv, short_options, long_options, 368 | NULL)) != (char)-1) { 369 | switch (option) { 370 | case 'h': 371 | usage(stdout, argc, argv); 372 | exit(EXIT_SUCCESS); 373 | break; 374 | case 'n': 375 | strcpy(dev_name, optarg); 376 | if (!strcmp(dev_name, "")) { 377 | printf("No dev file name!\n"); 378 | usage(stdout, argc, argv); 379 | exit(EXIT_FAILURE); 380 | } 381 | break; 382 | case 't': 383 | xfer_dir = 1; 384 | break; 385 | case 'r': 386 | xfer_dir = 0; 387 | break; 388 | case 'i': 389 | EID = strtoul(optarg, 0, 0); 390 | break; 391 | case 'b': 392 | BUS = strtoul(optarg, 0, 0); 393 | break; 394 | case 'd': 395 | DEV = strtoul(optarg, 0, 0); 396 | break; 397 | case 'f': 398 | FUN = strtoul(optarg, 0, 0); 399 | break; 400 | case 'o': 401 | routing = strtoul(optarg, 0, 0); 402 | break; 403 | case 'l': 404 | length = strtoul(optarg, 0, 0); 405 | break; 406 | case 'c': 407 | cont = strtoul(optarg, 0, 0); 408 | if (cont == 0) 409 | infinity_loop = 1; 410 | break; 411 | case 's': 412 | som = strtoul(optarg, 0, 0); 413 | break; 414 | case 'e': 415 | eom = strtoul(optarg, 0, 0); 416 | break; 417 | default: 418 | usage(stdout, argc, argv); 419 | exit(EXIT_FAILURE); 420 | break; 421 | } 422 | } 423 | 424 | if ((!length) && xfer_dir) { 425 | usage(stdout, argc, argv); 426 | return -1; 427 | } 428 | 429 | astpcie = aspeed_mctp_init(dev_name); 430 | if (astpcie == NULL) { 431 | printf("Please check mctp driver\n"); 432 | return -1; 433 | } 434 | ret = aspeed_mctp_register_default_handler(astpcie); 435 | if (ret < 0) 436 | return ret; 437 | 438 | ret = aspeed_mctp_get_mtu(astpcie); 439 | if (ret < 0) 440 | return ret; 441 | 442 | srand(time(NULL)); 443 | 444 | if (!xfer_dir) { 445 | times = 0; 446 | mctp_xfer.header = malloc(ASPEED_MCTP_XFER_SIZE + 447 | ASPEED_MCTP_PCIE_VDM_HDR_SIZE); 448 | mctp_xfer.xfer_buff = 449 | (unsigned char *)(mctp_xfer.header + 450 | ASPEED_MCTP_PCIE_VDM_HDR_SIZE_DW); 451 | } 452 | 453 | while (1) { 454 | if (xfer_dir) { 455 | if (aspeed_mctp_tx(astpcie, length, BUS, DEV, FUN, EID, 456 | routing, som, eom)) 457 | break; 458 | if (!infinity_loop) { 459 | cont--; 460 | if (cont == 0) 461 | break; 462 | } 463 | } else { 464 | rx_flag = aspeed_mctp_rx(astpcie, &mctp_xfer); 465 | if (rx_flag == 1) { 466 | printf("[%d] : Fail\n", times); 467 | break; 468 | } else if (rx_flag == 0) { 469 | printf("[%d] : PASS\n", times); 470 | times++; 471 | } 472 | if (times >= cont && cont != 0) 473 | break; 474 | } 475 | } 476 | wait_for_xfer_done(astpcie); 477 | 478 | aspeed_mctp_free(astpcie); 479 | if (!xfer_dir) 480 | free(mctp_xfer.header); 481 | 482 | return 0; 483 | } 484 | -------------------------------------------------------------------------------- /mem_utils/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CC = $(CROSS_COMPILE)gcc 8 | MYCFLAGS = -Wall -ansi 9 | INCLUDE = . 10 | OBJS = mem_common.h 11 | LDLIBS = -lc -lrt -lgcc 12 | EXTRA_FLAGS = -lpthread 13 | 14 | EXEC_MW = mw 15 | OBJS_MW = mw.o mem_common.o 16 | 17 | EXEC_MD = md 18 | OBJS_MD = md.o mem_common.o 19 | 20 | all: $(EXEC_MW) $(EXEC_MD) 21 | 22 | mw: $(OBJS_MW) 23 | $(CC) $(MYLDFLAGS) $(OBJS) $(OBJS_MW) -o $@ $(LDLIBS) $(EXTRA_FLAGS) 24 | chmod 744 $@ 25 | 26 | md: $(OBJS_MD) 27 | $(CC) $(MYLDFLAGS) $(OBJS) $(OBJS_MD) -o $@ $(LDLIBS) $(EXTRA_FLAGS) 28 | chmod 744 $@ 29 | 30 | mw.o: $(OBJS) mw.c 31 | $(CC) $(MYCFLAGS) -l$(INCLUDE) -c mw.c 32 | 33 | md.o: $(OBJS) md.c 34 | $(CC) $(MYCFLAGS) -l$(INCLUDE) -c md.c 35 | 36 | mem_common.o: $(OBJS) mem_common.c 37 | $(CC) $(MYCFLAGS) -l$(INCLUDE) -c mem_common.c 38 | 39 | clean: 40 | -rm -f *.elf *.gdb *.o $(EXEC_MW) $(EXEC_MD) 41 | 42 | install: 43 | cp $(EXEC_MW) $(EXEC_MD) $(INSTALL_DIR) 44 | -------------------------------------------------------------------------------- /mem_utils/compiler.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ */ 2 | /* 3 | * Keep all the ugly #ifdef for system stuff here 4 | */ 5 | 6 | #ifndef __COMPILER_H__ 7 | #define __COMPILER_H__ 8 | 9 | #ifdef __LP64__ 10 | #define MEM_SUPPORT_64BIT_DATA 1 11 | #else 12 | #define MEM_SUPPORT_64BIT_DATA 0 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /mem_utils/md.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Aspeed Technology Inc. 3 | */ 4 | #include "mem_common.h" 5 | 6 | int print_buffer (unsigned long, void *, unsigned int, unsigned int, unsigned int); 7 | 8 | unsigned long phy_addr = 0; 9 | 10 | #define DISP_LINE_LEN 16 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | unsigned long virt_addr, length; 15 | void * map_base; 16 | int size, fd; 17 | int rc = 0; 18 | unsigned long dp_last_addr=0, dp_last_size=0, dp_last_length=32; 19 | 20 | /* We use the last specified parameters, unless new ones are 21 | * entered. 22 | */ 23 | if (dp_last_addr) phy_addr = dp_last_addr; 24 | if (dp_last_size) size = dp_last_size; 25 | if (dp_last_length) length = dp_last_length; 26 | 27 | if (argc < 2) { 28 | printf ("Usage:\n%s\n", "md address range"); 29 | return 1; 30 | } 31 | 32 | fd = open("/dev/mem", O_RDWR|O_SYNC); 33 | if (fd == -1) 34 | { 35 | printf("open /dev/mem fail .. \n"); 36 | return (-1); 37 | } 38 | 39 | /* New command specified. Check for a size specification. 40 | * Defaults to long if no or incorrect specification. 41 | */ 42 | if ((size = cmd_get_data_size(argv[0], 4)) < 0) 43 | return 1; 44 | 45 | /* Address is specified since argc > 1 46 | addr = simple_strtoul(argv[1], NULL, 16); */ 47 | phy_addr = simple_strtoul(argv[1], NULL, 16); 48 | /* printf("addr = %08x \n", addr); */ 49 | 50 | map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, phy_addr & ~MAP_MASK); 51 | 52 | if(map_base == (void *) -1) { 53 | printf("mmap fail .. \n"); 54 | return (-1); 55 | } 56 | 57 | /* printf("mapping base = %08x , addr = %08x \n", map_base, addr); 58 | addr = map_base + (addr & MAP_MASK); */ 59 | virt_addr = (unsigned long)map_base + (phy_addr & MAP_MASK); 60 | 61 | /* If another parameter, it is the length to display. 62 | * Length is the number of objects, not number of bytes. 63 | */ 64 | if (argc > 2) 65 | length = simple_strtoul(argv[2], NULL, 16); 66 | 67 | /* Print the lines. */ 68 | print_buffer(virt_addr, (void*)virt_addr, size, length, DISP_LINE_LEN/size); 69 | phy_addr += size*length; 70 | 71 | dp_last_addr = phy_addr; 72 | dp_last_length = length; 73 | dp_last_size = size; 74 | if(munmap(map_base, MAP_SIZE) == -1) printf("mmap fail .. \n"); 75 | close(fd); 76 | return (rc); 77 | } 78 | 79 | #define MAX_LINE_LENGTH_BYTES (64) 80 | #define DEFAULT_LINE_LENGTH_BYTES (16) 81 | int print_buffer (unsigned long addr, void* data, unsigned int width, unsigned int count, unsigned int linelen) 82 | { 83 | unsigned char linebuf[MAX_LINE_LENGTH_BYTES]; 84 | unsigned int *uip = (void*)linebuf; 85 | unsigned short int *usp = (void*)linebuf; 86 | unsigned char *ucp = (void*)linebuf; 87 | int i; 88 | 89 | if (linelen*width > MAX_LINE_LENGTH_BYTES) 90 | linelen = MAX_LINE_LENGTH_BYTES / width; 91 | if (linelen < 1) 92 | linelen = DEFAULT_LINE_LENGTH_BYTES / width; 93 | 94 | while (count) { 95 | printf("%08lx:", phy_addr); 96 | 97 | /* check for overflow condition */ 98 | if (count < linelen) 99 | linelen = count; 100 | 101 | /* Copy from memory into linebuf and print hex values */ 102 | for (i = 0; i < linelen; i++) { 103 | if (width == 4) { 104 | uip[i] = *(volatile unsigned int *) data; 105 | printf(" %08x", uip[i]); 106 | } else if (width == 2) { 107 | usp[i] = *(volatile unsigned short int *) data; 108 | printf(" %04x", usp[i]); 109 | } else { 110 | ucp[i] = *(volatile unsigned char *) data; 111 | printf(" %02x", ucp[i]); 112 | } 113 | data += width; 114 | } 115 | #if 0 116 | /* Print data in ASCII characters */ 117 | puts(" "); 118 | for (i = 0; i < linelen * width; i++) 119 | putchar(isprint(ucp[i]) && (ucp[i] < 0x80) ? ucp[i] : '.'); 120 | #endif 121 | putchar ('\n'); 122 | 123 | /* update references */ 124 | addr += linelen * width; 125 | phy_addr += linelen * width; 126 | count -= linelen; 127 | } 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /mem_utils/mem_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Aspeed Technology Inc. 3 | */ 4 | #include "mem_common.h" 5 | #include "compiler.h" 6 | 7 | int cmd_get_data_size(char *arg, int default_size) 8 | { 9 | /* Check for a size specification .b, .w .l or .q. 10 | */ 11 | int len = strlen(arg); 12 | if (len > 2 && arg[len - 2] == '.') { 13 | switch (arg[len - 1]) { 14 | case 'b': 15 | return 1; 16 | case 'w': 17 | return 2; 18 | case 'l': 19 | return 4; 20 | case 's': 21 | return -2; 22 | case 'q': 23 | if (MEM_SUPPORT_64BIT_DATA) 24 | return 8; 25 | /* no break */ 26 | default: 27 | return -1; 28 | } 29 | } 30 | return default_size; 31 | } 32 | 33 | unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) 34 | { 35 | unsigned long result = 0,value; 36 | 37 | if (*cp == '0') { 38 | cp++; 39 | if ((*cp == 'x') && isxdigit(cp[1])) { 40 | base = 16; 41 | cp++; 42 | } 43 | if (!base) { 44 | base = 8; 45 | } 46 | } 47 | if (!base) { 48 | base = 10; 49 | } 50 | while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) 51 | ? toupper(*cp) : *cp)-'A'+10) < base) { 52 | /* printf("result = %x %s \n",result, cp); */ 53 | result = result*base + value; 54 | cp++; 55 | } 56 | if (endp) 57 | *endp = (char *)cp; 58 | return result; 59 | } 60 | 61 | long simple_strtol(const char *cp,char **endp,unsigned int base) 62 | { 63 | if(*cp=='-') 64 | return -simple_strtoul(cp+1,endp,base); 65 | return simple_strtoul(cp,endp,base); 66 | } 67 | -------------------------------------------------------------------------------- /mem_utils/mem_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Aspeed Technology Inc. 3 | */ 4 | #ifndef __MEM_COMMON_H 5 | #define __MEM_COMMON_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define MAP_SIZE 4096UL 18 | #define MAP_MASK (MAP_SIZE - 1) 19 | 20 | #define SPI_BASE 0x1e620000 21 | 22 | /* SPI DEF */ 23 | #define SPIM_CMD_WHA 0x01 24 | #define SPIM_CMD_RD 0x0B 25 | #define SPIM_CMD_DRD 0xBB 26 | #define SPIM_CMD_WR 0x02 27 | #define SPIM_CMD_DWR 0xD2 28 | #define SPIM_CMD_STA 0x05 29 | #define SPIM_CMD_ENBYTE 0x06 30 | #define SPIM_CMD_DISBYTE 0x04 31 | /* SPI END */ 32 | 33 | extern int cmd_get_data_size(char *, int); 34 | extern unsigned long simple_strtoul(const char *, char **, unsigned int); 35 | extern long simple_strtol(const char *, char **, unsigned int); 36 | 37 | #endif /* __MEM_COMMON_H */ 38 | 39 | -------------------------------------------------------------------------------- /mem_utils/mw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Aspeed Technology Inc. 3 | */ 4 | #include 5 | #include "mem_common.h" 6 | #include "compiler.h" 7 | 8 | /* Create a compile-time value */ 9 | #ifdef MEM_SUPPORT_64BIT_DATA 10 | #define SUPPORT_64BIT_DATA 1 11 | #else 12 | #define SUPPORT_64BIT_DATA 0 13 | #endif 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | unsigned long writeval; /* 64-bit if SUPPORT_64BIT_DATA */ 18 | unsigned long addr, count; 19 | int size; 20 | void *map_base; 21 | int fd; 22 | 23 | if ((argc < 3) || (argc > 4)) { 24 | printf("Usage:\n%s\n", "mw address value"); 25 | return 1; 26 | } 27 | 28 | /* Check for size specification. 29 | */ 30 | if ((size = cmd_get_data_size(argv[0], 4)) < 1) 31 | return 1; 32 | 33 | fd = open("/dev/mem", O_RDWR | O_SYNC); 34 | if (fd == -1) { 35 | printf("open /dev/mem fail ..\n"); 36 | return (-1); 37 | } 38 | 39 | /* Address is specified since argc > 1 40 | */ 41 | addr = simple_strtoul(argv[1], NULL, 16); 42 | 43 | map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 44 | addr & ~MAP_MASK); 45 | 46 | if (map_base == (void *)-1) { 47 | printf("mmap fail .. \n"); 48 | return (-1); 49 | } 50 | 51 | /*printf("mapping base = %08x , addr = %08x\n", map_base, addr); */ 52 | 53 | addr = (unsigned long)map_base + (addr & MAP_MASK); 54 | 55 | /* Get the value to write. 56 | */ 57 | writeval = simple_strtoul(argv[2], NULL, 16); 58 | 59 | /* Count ? */ 60 | if (argc == 4) { 61 | count = simple_strtoul(argv[3], NULL, 16); 62 | } else { 63 | count = 1; 64 | } 65 | 66 | while (count-- > 0) { 67 | if (size == 4) 68 | *((uint32_t *)addr) = (uint32_t)writeval; 69 | else if (SUPPORT_64BIT_DATA && size == 8) 70 | *((uint64_t *)addr) = writeval; 71 | else if (size == 2) 72 | *((uint16_t *)addr) = (uint16_t)writeval; 73 | else 74 | *((uint8_t *)addr) = (uint8_t)writeval; 75 | addr += size; 76 | } 77 | 78 | if (munmap(map_base, MAP_SIZE) == -1) 79 | printf("mmap fail ..\n"); 80 | close(fd); 81 | 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('aspeed-app', 'c', 'cpp', version: '1.0.0') 2 | thread_dep = dependency('threads') 3 | 4 | # rvas 5 | librvas = library('rvas', 'ast_rvas/rvas_lib/rvas.c', install: true, version: meson.project_version(), 6 | dependencies: thread_dep, include_directories: include_directories('ast_rvas/rvas_lib')) 7 | executable('vtest', ['ast_rvas/vtest.c'], install: true, link_with: librvas, 8 | dependencies: thread_dep, include_directories: include_directories('ast_rvas/rvas_lib')) 9 | executable('rvas_test', ['ast_rvas/rvas_test.c'], install: true, link_with: librvas, 10 | dependencies: thread_dep, include_directories: include_directories('ast_rvas/rvas_lib')) 11 | 12 | # Video 13 | executable('ast-video', ['video/ikvm_video.cpp', 'video/main1.cc', 'video/main2.cc', 'video/main.cc', 'video/video.cc', 'video/bmp.cc'], install: true) 14 | install_data('video/video.inf') 15 | 16 | # i2c 17 | executable('i2c-test', 'i2c-test/i2c-test.c', install: true, 18 | dependencies: thread_dep) 19 | 20 | executable('i2c-slave-mqueue', 'i2c-slave-mqueue/i2c-slave-mqueue.c', install: true) 21 | 22 | # i3c 23 | executable('i3c-test', 'i3c-test/i3c-test.c', install: true) 24 | 25 | # mctp-i3c 26 | executable('mctp-i3c', 'mctp-i3c/mctp-i3c.c', install: true) 27 | 28 | # mctp-socket 29 | executable('mctp-skt-req', 'mctp-socket/mctp-req.c', 'mctp-socket/mctp-util.c', install: true) 30 | executable('mctp-skt-recv', 'mctp-socket/mctp-recv.c', install: true) 31 | 32 | # eSPI 33 | executable('oob-pch-test', 'espi_test/oob-pch-test.c', install: true) 34 | 35 | # mctp 36 | executable('mctp-ast', ['mctp/mctp.c', 'mctp/libmctp.c'], install: true, 37 | include_directories: include_directories('mctp'), dependencies: thread_dep) 38 | 39 | # mem_utils 40 | executable('md', ['mem_utils/md.c', 'mem_utils/mem_common.c'], install: true) 41 | executable('mw', ['mem_utils/mw.c', 'mem_utils/mem_common.c'], install: true) 42 | 43 | # svf 44 | executable('svf', ['svf/main.c', 'svf/ast-jtag.c', 'svf/svf.c'], install: true) 45 | 46 | # otp 47 | executable('otp', 'otp/otp_ast2600.c', install: true, dependencies: dependency('openssl'), 48 | include_directories: include_directories('otp')) 49 | 50 | # usb 51 | executable('hid_gadget_app', 'usb/hid_gadget_test.c', install: true) 52 | 53 | -------------------------------------------------------------------------------- /otp/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CFLAGS += -Wall -Werror -lcrypto 8 | ifeq ($(ARCH),arm) 9 | OBJS = otp_ast2600.o 10 | endif 11 | ifeq ($(ARCH),arm64) 12 | OBJS = otp_ast2700.o lib_otp_ast2700.o 13 | SHARED_LIB = lib_otp.so 14 | endif 15 | 16 | EXE = otp_app 17 | CC = $(CROSS_COMPILE)gcc 18 | 19 | .c.o: 20 | $(CC) $(CFLAGS) -c $< 21 | 22 | $(EXE): $(OBJS) $(SHARED_LIB) 23 | $(CC) $(CFLAGS) $(OBJS) -o $@ 24 | 25 | ifeq ($(ARCH),arm64) 26 | $(SHARED_LIB): lib_otp_ast2700.c otp_prov.c 27 | $(CC) -shared -fPIC $^ -o $@ -lcrypto -lssl 28 | endif 29 | 30 | clean: 31 | rm -f $(EXE) $(OBJS) $(SHARED_LIB) 32 | 33 | install: 34 | cp $(EXE) $(INSTALL_DIR) 35 | 36 | -------------------------------------------------------------------------------- /otp/aspeed-otp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (C) 2021 ASPEED Technology Inc. 4 | */ 5 | 6 | #ifndef _UAPI_LINUX_ASPEED_OTP_H 7 | #define _UAPI_LINUX_ASPEED_OTP_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | struct otp_read { 14 | unsigned int offset; 15 | unsigned int len; 16 | uint8_t *data; 17 | }; 18 | 19 | struct otp_prog { 20 | unsigned int dw_offset; 21 | unsigned int bit_offset; 22 | unsigned int value; 23 | unsigned int w_offset; 24 | unsigned int len; 25 | uint8_t *data; 26 | }; 27 | 28 | struct otp_revid { 29 | uint32_t revid0; 30 | uint32_t revid1; 31 | }; 32 | 33 | #define OTP_A0 0 34 | #define OTP_A1 1 35 | #define OTP_A2 2 36 | #define OTP_A3 3 37 | 38 | #define OTPIOC_BASE 'O' 39 | 40 | #define ASPEED_OTP_READ_DATA _IOR(OTPIOC_BASE, 0, struct otp_read) 41 | #define ASPEED_OTP_READ_CONF _IOR(OTPIOC_BASE, 1, struct otp_read) 42 | #define ASPEED_OTP_PROG_DATA _IOW(OTPIOC_BASE, 2, struct otp_prog) 43 | #define ASPEED_OTP_PROG_CONF _IOW(OTPIOC_BASE, 3, struct otp_prog) 44 | #define ASPEED_OTP_VER _IOR(OTPIOC_BASE, 4, unsigned int) 45 | #define ASPEED_OTP_SW_RID _IOR(OTPIOC_BASE, 5, u32 *) 46 | #define ASPEED_SEC_KEY_NUM _IOR(OTPIOC_BASE, 6, u32 *) 47 | #define ASPEED_OTP_GET_ECC _IOR(OTPIOC_BASE, 7, uint32_t) 48 | #define ASPEED_OTP_SET_ECC _IO(OTPIOC_BASE, 8) 49 | #define ASPEED_OTP_GET_REVID _IOR(OTPIOC_BASE, 9, struct otp_revid) 50 | 51 | #endif /* _UAPI_LINUX_ASPEED_OTP_H */ 52 | -------------------------------------------------------------------------------- /otp/otp_ast2600.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (C) 2021 ASPEED Technology Inc. 4 | */ 5 | 6 | #ifndef _UAPI_LINUX_OTP_AST2600_H 7 | #define _UAPI_LINUX_OTP_AST2600_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | struct otp_read { 14 | unsigned int offset; 15 | unsigned int len; 16 | unsigned int *data; 17 | }; 18 | 19 | struct otp_prog { 20 | unsigned int dw_offset; 21 | unsigned int bit_offset; 22 | unsigned int value; 23 | }; 24 | 25 | #define OTP_A0 0 26 | #define OTP_A1 1 27 | #define OTP_A2 2 28 | #define OTP_A3 3 29 | 30 | #define OTPIOC_BASE 'O' 31 | 32 | #define ASPEED_OTP_READ_DATA _IOR(OTPIOC_BASE, 0, struct otp_read) 33 | #define ASPEED_OTP_READ_CONF _IOR(OTPIOC_BASE, 1, struct otp_read) 34 | #define ASPEED_OTP_PROG_DATA _IOW(OTPIOC_BASE, 2, struct otp_prog) 35 | #define ASPEED_OTP_PROG_CONF _IOW(OTPIOC_BASE, 3, struct otp_prog) 36 | #define ASPEED_OTP_VER _IOR(OTPIOC_BASE, 4, unsigned int) 37 | #define ASPEED_OTP_SW_RID _IOR(OTPIOC_BASE, 5, u32 *) 38 | #define ASPEED_SEC_KEY_NUM _IOR(OTPIOC_BASE, 6, u32 *) 39 | 40 | #endif /* _UAPI_LINUX_OTP_AST2600_H */ 41 | -------------------------------------------------------------------------------- /otp/otp_ast2700.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #ifndef OTP_AST2700_H 4 | #define OTP_AST2700_H 5 | 6 | #include 7 | #include 8 | #include "utils.h" 9 | 10 | enum otp_region { 11 | OTP_REGION_ROM, 12 | OTP_REGION_RBP, 13 | OTP_REGION_CONF, 14 | OTP_REGION_STRAP, 15 | OTP_REGION_STRAP_EXT, 16 | OTP_REGION_STRAP_EXT_VLD, 17 | OTP_REGION_USER_DATA, 18 | OTP_REGION_SECURE, 19 | OTP_REGION_CALIPTRA, 20 | OTP_REGION_PUF, 21 | }; 22 | 23 | enum otp_status { 24 | OTP_FAILURE = -2, 25 | OTP_USAGE = -1, 26 | OTP_SUCCESS = 0, 27 | OTP_PROG_SKIP, 28 | }; 29 | 30 | #define OTP_VER "1.1.0" 31 | 32 | #define OTP_AST2700_A0 0 33 | #define OTP_AST2700_A1 1 34 | 35 | #define ID0_AST2700A0 0x06000003 36 | #define ID1_AST2700A0 0x06000003 37 | #define ID0_AST2750A1 0x06010003 38 | #define ID1_AST2750A1 0x06010003 39 | #define ID0_AST2700A1 0x06010103 40 | #define ID1_AST2700A1 0x06010103 41 | 42 | #define SOC_AST2700A0 8 43 | #define SOC_AST2700A1 9 44 | 45 | /* OTP memory address from 0x0~0x2000. (unit: Single Word 16-bits) */ 46 | /* ---- 0x0 ----- 47 | * ROM 48 | * ---- 0x3e0 ----- 49 | * RBP 50 | * ---- 0x400 ----- 51 | * CONF 52 | * ---- 0x420 ----- 53 | * STRAP 54 | * ---- 0x430 ----- 55 | * STRAP EXT 56 | * ---- 0x440 ----- 57 | * User Region 58 | * ---- 0x1000 ---- 59 | * Secure Region 60 | * ---- 0x1c00 ---- 61 | * Caliptra 62 | * ---- 0x1f80 ---- 63 | * SW PUF 64 | * ---- 0x1fc0 ---- 65 | * HW PUF 66 | * ---- 0x2000 ---- 67 | */ 68 | #define ROM_REGION_START_ADDR 0x0 69 | #define ROM_REGION_END_ADDR 0x3e0 70 | #define RBP_REGION_START_ADDR ROM_REGION_END_ADDR 71 | #define RBP_REGION_END_ADDR 0x400 72 | #define CONF_REGION_START_ADDR RBP_REGION_END_ADDR 73 | #define CONF_REGION_END_ADDR 0x420 74 | #define STRAP_REGION_START_ADDR CONF_REGION_END_ADDR 75 | #define STRAP_REGION_END_ADDR 0x430 76 | #define STRAPEXT_REGION_START_ADDR STRAP_REGION_END_ADDR 77 | #define STRAPEXT_REGION_END_ADDR 0x440 78 | #define USER_REGION_START_ADDR STRAPEXT_REGION_END_ADDR 79 | #define USER_REGION_END_ADDR 0x1000 80 | #define SEC_REGION_START_ADDR USER_REGION_END_ADDR 81 | #define SEC_REGION_END_ADDR 0x1c00 82 | #define CAL_REGION_START_ADDR SEC_REGION_END_ADDR 83 | #define CAL_REGION_END_ADDR 0x1f80 84 | #define SW_PUF_REGION_START_ADDR CAL_REGION_END_ADDR 85 | #define SW_PUF_REGION_END_ADDR 0x1fc0 86 | #define HW_PUF_REGION_START_ADDR SW_PUF_REGION_END_ADDR 87 | #define HW_PUF_REGION_END_ADDR 0x2000 88 | 89 | #define OTP_MEM_ADDR_MAX HW_PUF_REGION_START_ADDR 90 | #define OTP_ROM_REGION_SIZE (ROM_REGION_END_ADDR - ROM_REGION_START_ADDR) 91 | #define OTP_RBP_REGION_SIZE (RBP_REGION_END_ADDR - RBP_REGION_START_ADDR) 92 | #define OTP_CONF_REGION_SIZE (CONF_REGION_END_ADDR - CONF_REGION_START_ADDR) 93 | #define OTP_STRAP_REGION_SIZE (STRAP_REGION_END_ADDR - STRAP_REGION_START_ADDR) 94 | #define OTP_STRAP_EXT_REGION_SIZE (STRAPEXT_REGION_END_ADDR - STRAPEXT_REGION_START_ADDR) 95 | #define OTP_USER_REGION_SIZE (USER_REGION_END_ADDR - USER_REGION_START_ADDR) 96 | #define OTP_SEC_REGION_SIZE (SEC_REGION_END_ADDR - SEC_REGION_START_ADDR) 97 | #define OTP_CAL_REGION_SIZE (CAL_REGION_END_ADDR - CAL_REGION_START_ADDR) 98 | #define OTP_PUF_REGION_SIZE (HW_PUF_REGION_END_ADDR - SW_PUF_REGION_START_ADDR) 99 | 100 | /* OTPRBP */ 101 | #define OTPRBP0_ADDR OTPRBP_START_ADDR 102 | #define OTPRBP1_ADDR 0x1 103 | #define OTPRBP2_ADDR 0x2 104 | #define OTPRBP3_ADDR 0x3 105 | #define OTPRBP4_ADDR 0x4 106 | #define OTPRBP8_ADDR 0x8 107 | #define OTPRBP10_ADDR 0xa 108 | #define OTPRBP18_ADDR 0x12 109 | 110 | #define SOC_ECC_KEY_RETIRE OTPRBP0_ADDR 111 | #define SOC_LMS_KEY_RETIRE OTPRBP1_ADDR 112 | #define CAL_OWN_KEY_RETURE OTPRBP3_ADDR 113 | #define SOC_HW_SVN_ADDR OTPRBP4_ADDR 114 | #define CAL_FMC_HW_SVN_ADDR OTPRBP8_ADDR 115 | #define CAL_RT_HW_SVN_ADDR OTPRBP10_ADDR 116 | #define CAL_MANU_ECC_KEY_MASK OTPRBP18_ADDR 117 | 118 | #define OTP_DEVICE_NAME_0 "otp@14c07000" 119 | #define OTP_DEVICE_NAME_1 "otp@30c07000" 120 | 121 | #define OTP_MAGIC "SOCOTP" 122 | #define CHECKSUM_LEN 48 123 | #define OTP_INC_ROM BIT(31) 124 | #define OTP_INC_RBP BIT(30) 125 | #define OTP_INC_CONFIG BIT(29) 126 | #define OTP_INC_STRAP BIT(28) 127 | #define OTP_INC_STRAP_EXT BIT(27) 128 | #define OTP_INC_SECURE BIT(26) 129 | #define OTP_INC_CALIPTRA BIT(25) 130 | #define OTP_REGION_SIZE(info) (((info) >> 16) & 0xffff) 131 | #define OTP_REGION_OFFSET(info) ((info) & 0xffff) 132 | #define OTP_IMAGE_SIZE(info) ((info) & 0xffff) 133 | 134 | /* OTP key header format */ 135 | #define OTP_KH_NUM 80 136 | #define OTP_KH_KEY_ID(kh) ((kh) & 0xf) 137 | #define OTP_KH_KEY_TYPE(kh) (((kh) >> 4) & 0x7) 138 | #define OTP_KH_LAST(kh) (((kh) >> 15) & 0x1) 139 | #define OTP_KH_OFFSET(kh) (((kh) >> 16) & 0xfff) 140 | 141 | enum command_ret_t { 142 | CMD_RET_SUCCESS, /* 0 = Success */ 143 | CMD_RET_FAILURE, /* 1 = Failure */ 144 | CMD_RET_USAGE = -1, /* Failure, please report 'usage' error */ 145 | }; 146 | 147 | enum otp_ioctl_cmds { 148 | GET_ECC_STATUS = 1, 149 | SET_ECC_ENABLE, 150 | }; 151 | 152 | enum otp_ecc_codes { 153 | OTP_ECC_MISMATCH = -1, 154 | OTP_ECC_DISABLE = 0, 155 | OTP_ECC_ENABLE = 1, 156 | }; 157 | 158 | struct otp_header { 159 | uint8_t otp_magic[8]; 160 | uint32_t soc_ver; 161 | uint32_t otptool_ver; 162 | uint32_t image_info; 163 | uint32_t rom_info; 164 | uint32_t rbp_info; 165 | uint32_t config_info; 166 | uint32_t strap_info; 167 | uint32_t strap_ext_info; 168 | uint32_t secure_info; 169 | uint32_t cptra_info; 170 | uint32_t checksum_offset; 171 | }; 172 | 173 | struct otpstrap_status { 174 | int value; 175 | int option_value[6]; 176 | int remain_times; 177 | int writeable_option; 178 | int protected; 179 | }; 180 | 181 | union otp_pro_sts { 182 | uint32_t value; 183 | struct { 184 | char r_prot_strap_ext : 1; 185 | char r_prot_rom : 1; 186 | char r_prot_conf : 1; 187 | char r_prot_strap : 1; 188 | char w_prot_strap_ext : 1; 189 | char w_prot_rom : 1; 190 | char w_prot_conf : 1; 191 | char w_prot_strap : 1; 192 | char retire_option : 1; 193 | char en_sec_boot : 1; 194 | char w_prot_rbp : 1; 195 | char r_prot_cal : 1; 196 | char w_prot_cal : 1; 197 | char dis_otp_bist : 1; 198 | char w_prot_puf : 1; 199 | char mem_lock : 1; 200 | } fields; 201 | }; 202 | 203 | struct otp_info_cb { 204 | int otp_fd; 205 | int version; 206 | char ver_name[3]; 207 | const struct otprbp_info *rbp_info; 208 | int rbp_info_len; 209 | const struct otpconf_info *conf_info; 210 | int conf_info_len; 211 | const struct otpstrap_info *strap_info; 212 | int strap_info_len; 213 | const struct otpstrap_ext_info *strap_ext_info; 214 | int strap_ext_info_len; 215 | const struct otpcal_info *cal_info; 216 | int cal_info_len; 217 | const struct otpkey_type *key_info; 218 | int key_info_len; 219 | union otp_pro_sts pro_sts; 220 | }; 221 | 222 | struct otp_image_layout { 223 | int rom_length; 224 | int rbp_length; 225 | int conf_length; 226 | int strap_length; 227 | int strap_ext_length; 228 | int secure_length; 229 | int cptra_length; 230 | uint8_t *rom; 231 | uint8_t *rbp; 232 | uint8_t *conf; 233 | uint8_t *strap; 234 | uint8_t *strap_ext; 235 | uint8_t *secure; 236 | uint8_t *cptra; 237 | }; 238 | 239 | uint32_t chip_version(void); 240 | int confirm_yesno(void); 241 | void buf_print(uint8_t *buf, int len); 242 | 243 | int otp_read_rom(uint32_t offset, uint16_t *data); 244 | int otp_read_rbp(uint32_t offset, uint16_t *data); 245 | int otp_read_conf(uint32_t offset, uint16_t *data); 246 | int otp_read_strap(uint32_t offset, uint16_t *data); 247 | int otp_read_strap_ext(uint32_t offset, uint16_t *data); 248 | int otp_read_strap_ext_vld(uint32_t offset, uint16_t *data); 249 | int otp_read_udata(uint32_t offset, uint16_t *data); 250 | int otp_read_sdata(uint32_t offset, uint16_t *data); 251 | int otp_read_sdata_multi(uint32_t offset, uint16_t *data, int num); 252 | int otp_read_cptra(uint32_t offset, uint16_t *data); 253 | int otp_read_swpuf(uint32_t offset, uint16_t *data); 254 | 255 | int otp_prog(uint32_t offset, uint16_t data); 256 | int otp_prog_multi(uint32_t offset, uint16_t *data, int num); 257 | int otp_prog_data(int mode, int otp_w_offset, int bit_offset, 258 | int value, int nconfirm, bool debug); 259 | 260 | int otp_verify_image(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf); 261 | int otp_prog_image_region(struct otp_image_layout *image_layout, enum otp_region region_type); 262 | int otp_prog_strap_image(struct otp_image_layout *image_layout, 263 | struct otpstrap_status *otpstrap); 264 | int otp_prog_strap_ext_image(struct otp_image_layout *image_layout); 265 | 266 | extern struct otp_info_cb info_cb; 267 | 268 | struct otp_read { 269 | unsigned int offset; 270 | unsigned int len; 271 | uint8_t *data; 272 | }; 273 | 274 | struct otp_prog { 275 | unsigned int w_offset; 276 | unsigned int len; 277 | uint8_t *data; 278 | }; 279 | 280 | struct otp_revid { 281 | uint32_t revid0; 282 | uint32_t revid1; 283 | }; 284 | 285 | #define OTPIOC_BASE 'O' 286 | 287 | #define ASPEED_OTP_READ_DATA _IOR(OTPIOC_BASE, 0, struct otp_read) 288 | #define ASPEED_OTP_READ_CONF _IOR(OTPIOC_BASE, 1, struct otp_read) 289 | #define ASPEED_OTP_PROG_DATA _IOW(OTPIOC_BASE, 2, struct otp_prog) 290 | #define ASPEED_OTP_PROG_CONF _IOW(OTPIOC_BASE, 3, struct otp_prog) 291 | #define ASPEED_OTP_VER _IOR(OTPIOC_BASE, 4, unsigned int) 292 | #define ASPEED_OTP_SW_RID _IOR(OTPIOC_BASE, 5, u32 *) 293 | #define ASPEED_SEC_KEY_NUM _IOR(OTPIOC_BASE, 6, u32 *) 294 | #define ASPEED_OTP_GET_ECC _IOR(OTPIOC_BASE, 7, uint32_t) 295 | #define ASPEED_OTP_SET_ECC _IO(OTPIOC_BASE, 8) 296 | #define ASPEED_OTP_GET_REVID _IOR(OTPIOC_BASE, 9, struct otp_revid) 297 | 298 | #endif /* OTP_AST2700_H */ 299 | -------------------------------------------------------------------------------- /otp/otp_prov.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0+ 2 | /* 3 | * Copyright 2024 Aspeed Technology Inc. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "otp_ast2700.h" 13 | #include "otp_info_ast2700.h" 14 | 15 | bool lib_otp_is_init; 16 | 17 | int lib_otp_init(void) 18 | { 19 | uint32_t ver; 20 | 21 | info_cb.otp_fd = open("/dev/aspeed-otp", O_RDWR); 22 | if (info_cb.otp_fd == -1) { 23 | printf("Can't open /dev/aspeed-otp, please install driver!!\n"); 24 | return -EIO; 25 | } 26 | 27 | ver = chip_version(); 28 | switch (ver) { 29 | case OTP_AST2700_A1: 30 | printf("Chip: AST2700-A1\n"); 31 | info_cb.version = OTP_AST2700_A1; 32 | info_cb.rbp_info = a1_rbp_info; 33 | info_cb.rbp_info_len = ARRAY_SIZE(a1_rbp_info); 34 | info_cb.conf_info = a1_conf_info; 35 | info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 36 | info_cb.strap_info = a1_strap_info; 37 | info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 38 | info_cb.strap_ext_info = a1_strap_ext_info; 39 | info_cb.strap_ext_info_len = ARRAY_SIZE(a1_strap_ext_info); 40 | info_cb.cal_info = a1_cal_info; 41 | info_cb.cal_info_len = ARRAY_SIZE(a1_cal_info); 42 | info_cb.key_info = a1_key_type; 43 | info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 44 | break; 45 | default: 46 | printf("SOC is not supported\n"); 47 | return CMD_RET_FAILURE; 48 | } 49 | 50 | lib_otp_is_init = true; 51 | 52 | return 0; 53 | } 54 | 55 | int lib_otp_read_data(int mode, int offset, int w_count, uint16_t *output) 56 | { 57 | int (*otp_read_func)(uint32_t offset, uint16_t *data); 58 | uint16_t *data = output; 59 | int range; 60 | int rc; 61 | 62 | if (!lib_otp_is_init) { 63 | rc = lib_otp_init(); 64 | if (rc) { 65 | printf("lib OTP init failed\n"); 66 | goto end; 67 | } 68 | } 69 | 70 | if (!output) { 71 | printf("Invalid parameters\n"); 72 | rc = -EINVAL; 73 | goto end; 74 | } 75 | 76 | switch (mode) { 77 | case OTP_REGION_ROM: 78 | otp_read_func = otp_read_rom; 79 | range = OTP_ROM_REGION_SIZE; 80 | break; 81 | case OTP_REGION_RBP: 82 | otp_read_func = otp_read_rbp; 83 | range = OTP_RBP_REGION_SIZE; 84 | break; 85 | case OTP_REGION_CONF: 86 | otp_read_func = otp_read_conf; 87 | range = OTP_CONF_REGION_SIZE; 88 | break; 89 | case OTP_REGION_STRAP: 90 | otp_read_func = otp_read_strap; 91 | range = OTP_STRAP_REGION_SIZE; 92 | break; 93 | case OTP_REGION_STRAP_EXT: 94 | otp_read_func = otp_read_strap_ext; 95 | range = OTP_STRAP_EXT_REGION_SIZE / 2; 96 | break; 97 | case OTP_REGION_STRAP_EXT_VLD: 98 | otp_read_func = otp_read_strap_ext_vld; 99 | range = OTP_STRAP_EXT_REGION_SIZE / 2; 100 | break; 101 | case OTP_REGION_USER_DATA: 102 | otp_read_func = otp_read_udata; 103 | range = OTP_USER_REGION_SIZE; 104 | break; 105 | case OTP_REGION_SECURE: 106 | otp_read_func = otp_read_sdata; 107 | range = OTP_SEC_REGION_SIZE; 108 | break; 109 | case OTP_REGION_CALIPTRA: 110 | otp_read_func = otp_read_cptra; 111 | range = OTP_CAL_REGION_SIZE; 112 | break; 113 | case OTP_REGION_PUF: 114 | otp_read_func = otp_read_swpuf; 115 | range = OTP_PUF_REGION_SIZE; 116 | break; 117 | default: 118 | printf("mode %d is not supported\n", mode); 119 | return -EINVAL; 120 | } 121 | 122 | if (offset + w_count > range) { 123 | printf("Out of range\n"); 124 | rc = -EINVAL; 125 | goto end; 126 | } 127 | 128 | for (int i = 0; i < w_count; i++) { 129 | otp_read_func(offset + i, data + i); 130 | // printf("read data[%d]: 0x%x:0x%x\n", offset + i, 131 | // (uintptr_t)(data + i), *(data + i)); 132 | } 133 | 134 | return 0; 135 | 136 | end: 137 | return rc; 138 | } 139 | 140 | int lib_otp_prog_data(int mode, int offset, int w_count, uint16_t *input) 141 | { 142 | uint32_t prog_address; 143 | int range; 144 | int rc; 145 | 146 | if (!lib_otp_is_init) { 147 | rc = lib_otp_init(); 148 | if (rc) { 149 | printf("lib OTP init failed\n"); 150 | goto end; 151 | } 152 | } 153 | 154 | if (!input) { 155 | printf("Invalid parameters\n"); 156 | rc = -EINVAL; 157 | goto end; 158 | } 159 | 160 | switch (mode) { 161 | case OTP_REGION_CALIPTRA: 162 | prog_address = CAL_REGION_START_ADDR + offset; 163 | range = OTP_CAL_REGION_SIZE; 164 | break; 165 | default: 166 | printf("mode %d is not supported\n", mode); 167 | break; 168 | } 169 | 170 | if (offset + w_count > range) { 171 | printf("Out of range\n"); 172 | rc = -EINVAL; 173 | goto end; 174 | } 175 | 176 | for (int i = 0; i < w_count; i++) { 177 | rc = otp_prog(prog_address, *input); 178 | printf("OTP prog 0x%x=0x%x\n", prog_address, *input); 179 | if (rc) { 180 | printf("OTP prog failed\n"); 181 | goto end; 182 | } 183 | prog_address++; 184 | input++; 185 | } 186 | 187 | return 0; 188 | end: 189 | return rc; 190 | } 191 | 192 | int lib_otp_prog_image(char *path) 193 | { 194 | struct otp_image_layout image_layout; 195 | struct otpstrap_status otpstrap[32]; 196 | struct otp_header *otp_header; 197 | int image_soc_ver = 0; 198 | int image_size; 199 | int ret = 0; 200 | uint8_t *checksum; 201 | uint8_t *buf; 202 | long fsize; 203 | FILE *fd; 204 | int rc; 205 | 206 | if (!lib_otp_is_init) { 207 | rc = lib_otp_init(); 208 | if (rc) { 209 | printf("lib OTP init failed\n"); 210 | goto end; 211 | } 212 | } 213 | 214 | fd = fopen(path, "rb"); 215 | if (!fd) { 216 | printf("failed to open %s\n", path); 217 | ret = OTP_FAILURE; 218 | goto end; 219 | } 220 | fseek(fd, 0, SEEK_END); 221 | fsize = ftell(fd); 222 | fseek(fd, 0, SEEK_SET); 223 | buf = malloc(fsize + 1); 224 | ret = fread(buf, 1, fsize, fd); 225 | if (ret != fsize) { 226 | printf("Reading \"%s\" failed\n", path); 227 | ret = OTP_FAILURE; 228 | goto end; 229 | } 230 | fclose(fd); 231 | buf[fsize] = 0; 232 | 233 | otp_header = (struct otp_header *)buf; 234 | if (!otp_header) { 235 | printf("Failed to map physical memory\n"); 236 | ret = OTP_FAILURE; 237 | goto end; 238 | } 239 | 240 | image_size = OTP_IMAGE_SIZE(otp_header->image_info); 241 | printf("image_info:0x%x image_size: 0x%x\n", otp_header->image_info, image_size); 242 | 243 | checksum = buf + otp_header->checksum_offset; 244 | 245 | /* Check Image Magic */ 246 | if (strncmp(OTP_MAGIC, (char *)otp_header->otp_magic, strlen(OTP_MAGIC)) != 0) { 247 | printf("Image is invalid, magic 0x%x should be %s\n", 248 | *(uint32_t *)otp_header->otp_magic, OTP_MAGIC); 249 | ret = OTP_FAILURE; 250 | goto end; 251 | } 252 | 253 | image_layout.rom_length = OTP_REGION_SIZE(otp_header->rom_info); 254 | image_layout.rom = buf + OTP_REGION_OFFSET(otp_header->rom_info); 255 | 256 | image_layout.rbp_length = OTP_REGION_SIZE(otp_header->rbp_info); 257 | image_layout.rbp = buf + OTP_REGION_OFFSET(otp_header->rbp_info); 258 | 259 | image_layout.conf_length = OTP_REGION_SIZE(otp_header->config_info); 260 | image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info); 261 | 262 | image_layout.strap_length = OTP_REGION_SIZE(otp_header->strap_info); 263 | image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info); 264 | 265 | image_layout.strap_ext_length = OTP_REGION_SIZE(otp_header->strap_ext_info); 266 | image_layout.strap_ext = buf + OTP_REGION_OFFSET(otp_header->strap_ext_info); 267 | 268 | image_layout.secure_length = OTP_REGION_SIZE(otp_header->secure_info); 269 | image_layout.secure = buf + OTP_REGION_OFFSET(otp_header->secure_info); 270 | 271 | image_layout.cptra_length = OTP_REGION_SIZE(otp_header->cptra_info); 272 | image_layout.cptra = buf + OTP_REGION_OFFSET(otp_header->cptra_info); 273 | 274 | if (otp_header->soc_ver == SOC_AST2700A1) { 275 | image_soc_ver = OTP_AST2700_A1; 276 | } else { 277 | printf("Image SOC Version is not supported\n"); 278 | ret = OTP_FAILURE; 279 | goto end; 280 | } 281 | 282 | if (image_soc_ver != info_cb.version) { 283 | printf("Image SOC version is not match to HW SOC version\n"); 284 | ret = OTP_FAILURE; 285 | goto end; 286 | } 287 | 288 | ret = otp_verify_image(buf, image_size, checksum); 289 | if (ret) { 290 | printf("checksum is invalid\n"); 291 | ret = OTP_FAILURE; 292 | goto end; 293 | } 294 | 295 | if (otp_header->image_info & OTP_INC_ROM) { 296 | printf("programing rom region ...\n"); 297 | ret = otp_prog_image_region(&image_layout, OTP_REGION_ROM); 298 | if (ret) { 299 | printf("Error\n"); 300 | goto end; 301 | } 302 | } 303 | if (otp_header->image_info & OTP_INC_RBP) { 304 | printf("programing rbp region ...\n"); 305 | ret = otp_prog_image_region(&image_layout, OTP_REGION_RBP); 306 | if (ret) { 307 | printf("Error\n"); 308 | goto end; 309 | } 310 | } 311 | if (otp_header->image_info & OTP_INC_SECURE) { 312 | printf("programing secure region ...\n"); 313 | ret = otp_prog_image_region(&image_layout, OTP_REGION_SECURE); 314 | if (ret) { 315 | printf("Error\n"); 316 | goto end; 317 | } 318 | } 319 | if (otp_header->image_info & OTP_INC_CONFIG) { 320 | printf("programing configuration region ...\n"); 321 | ret = otp_prog_image_region(&image_layout, OTP_REGION_CONF); 322 | if (ret != 0) { 323 | printf("Error\n"); 324 | goto end; 325 | } 326 | } 327 | if (otp_header->image_info & OTP_INC_STRAP) { 328 | printf("programing strap region ...\n"); 329 | ret = otp_prog_strap_image(&image_layout, otpstrap); 330 | if (ret != 0) { 331 | printf("Error\n"); 332 | goto end; 333 | } 334 | } 335 | if (otp_header->image_info & OTP_INC_STRAP_EXT) { 336 | printf("programing strap extension region ...\n"); 337 | ret = otp_prog_strap_ext_image(&image_layout); 338 | if (ret != 0) { 339 | printf("Error\n"); 340 | goto end; 341 | } 342 | } 343 | if (otp_header->image_info & OTP_INC_CALIPTRA) { 344 | printf("programing caliptra region ...\n"); 345 | ret = otp_prog_image_region(&image_layout, OTP_REGION_CALIPTRA); 346 | if (ret != 0) { 347 | printf("Error\n"); 348 | goto end; 349 | } 350 | } 351 | 352 | return OTP_SUCCESS; 353 | end: 354 | return ret; 355 | } 356 | -------------------------------------------------------------------------------- /otp/utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | 3 | #ifndef __UTILS_H__ 4 | #define __UTILS_H__ 5 | 6 | /* number of bits in a long int. */ 7 | #define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__) 8 | 9 | /* contiguous bitmask starting at bit 'h' and ending at bit 'l' */ 10 | #define GENMASK(h, l) (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) 11 | 12 | /* prepare bit mask */ 13 | #define BIT(n) (1 << (n)) 14 | 15 | /* calculate number of array elements */ 16 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) 17 | 18 | /* avoid unused variable warning */ 19 | #define UNUSED(x) ((void)(x)) 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /svf/LCMXO2-7000HE/erase.svf: -------------------------------------------------------------------------------- 1 | STATE RESET; 2 | HDR 0; 3 | HIR 0; 4 | TDR 0; 5 | TIR 0; 6 | ENDDR DRPAUSE; 7 | ENDIR IRPAUSE; 8 | ! FREQUENCY 1.00e+006 HZ; 9 | STATE IDLE; 10 | SIR 8 TDI (E0); 11 | SDR 32 TDI (00000000) 12 | TDO (012B5043) 13 | MASK (FFFFFFFF); 14 | SIR 8 TDI (1C); 15 | SDR 664 TDI (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 16 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 17 | FFFFFF); 18 | SIR 8 TDI (3C); 19 | RUNTEST IDLE 2 TCK 1.00E-003 SEC; 20 | SDR 32 TDI (00000000) 21 | TDO (00000000) 22 | MASK (00000020); 23 | SIR 8 TDI (C6); 24 | SDR 8 TDI (00); 25 | RUNTEST IDLE 2 TCK 1.00E-003 SEC; 26 | SIR 8 TDI (0E); 27 | SDR 8 TDI (01); 28 | RUNTEST IDLE 2 TCK 1.00E+000 SEC; 29 | SIR 8 TDI (FF) 30 | TDO (00) 31 | MASK (C0); 32 | SIR 8 TDI (C6); 33 | SDR 8 TDI (08); 34 | RUNTEST IDLE 2 TCK 1.00E-003 SEC; 35 | SIR 8 TDI (3C); 36 | RUNTEST IDLE 2 TCK 1.00E-003 SEC; 37 | SDR 32 TDI (00000000) 38 | TDO (00000000) 39 | MASK (00024040); 40 | SIR 8 TDI (0E); 41 | SDR 8 TDI (0E); 42 | RUNTEST IDLE 2 TCK 3.00E+001 SEC; 43 | SIR 8 TDI (F0); 44 | SDR 1 TDI (0) 45 | TDO (0); 46 | SIR 8 TDI (3C); 47 | RUNTEST IDLE 2 TCK 1.00E-003 SEC; 48 | SDR 32 TDI (00000000) 49 | TDO (00000000) 50 | MASK (00003000); 51 | SIR 8 TDI (26); 52 | RUNTEST IDLE 2 TCK 1.00E+000 SEC; 53 | SIR 8 TDI (FF); 54 | RUNTEST IDLE 100 TCK 1.00E-001 SEC; 55 | STATE RESET; 56 | -------------------------------------------------------------------------------- /svf/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CFLAGS += -Wall 8 | OBJS = main.o ast-jtag.o svf.o 9 | EXE = svf 10 | 11 | CC = $(CROSS_COMPILE)gcc 12 | 13 | .c.o: 14 | $(CC) $(CFLAGS) -c $< 15 | 16 | $(EXE): $(OBJS) 17 | $(CC) $(CFLAGS) $(OBJS) -o $@ 18 | 19 | clean: 20 | rm -f $(EXE) $(OBJS) 21 | 22 | install: 23 | cp $(EXE) $(INSTALL_DIR) 24 | 25 | -------------------------------------------------------------------------------- /svf/ast-jtag.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0+ 2 | /* 3 | * Copyright 2020 Aspeed Technology Inc. 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include "ast-jtag.h" 18 | 19 | int jtag_fd; 20 | 21 | #define DEBUG 0 22 | 23 | #if DEBUG 24 | #define ast_jtag_printf(...) printf(__VA_ARGS__) 25 | #else 26 | #define ast_jtag_printf(...) 27 | #endif 28 | 29 | /*************************************************************************************/ 30 | /* AST JTAG LIB */ 31 | int ast_jtag_open(char *dev) 32 | { 33 | jtag_fd = open(dev, O_RDWR); 34 | if (jtag_fd == -1) { 35 | printf("Can't open %s, please install driver!! \n", dev); 36 | return -1; 37 | } 38 | return 0; 39 | } 40 | 41 | void ast_jtag_close(void) 42 | { 43 | close(jtag_fd); 44 | } 45 | 46 | unsigned int ast_get_jtag_freq(void) 47 | { 48 | int retval; 49 | unsigned int freq = 0; 50 | retval = ioctl(jtag_fd, JTAG_GIOCFREQ, &freq); 51 | if (retval == -1) { 52 | perror("ioctl JTAG get freq fail!\n"); 53 | return 0; 54 | } 55 | 56 | return freq; 57 | } 58 | 59 | int ast_set_jtag_mode(uint8_t sw_mode) 60 | { 61 | struct jtag_mode jtag_mode; 62 | int retval; 63 | 64 | jtag_mode.feature = JTAG_XFER_MODE; 65 | jtag_mode.mode = sw_mode ? JTAG_XFER_SW_MODE : JTAG_XFER_HW_MODE; 66 | retval = ioctl(jtag_fd, JTAG_SIOCMODE, &jtag_mode); 67 | if (retval == -1) { 68 | perror("ioctl JTAG set mode fail!\n"); 69 | return -1; 70 | } 71 | return 0; 72 | } 73 | 74 | int ast_set_jtag_freq(unsigned int freq) 75 | { 76 | int retval; 77 | unsigned int jtag_freq = freq; 78 | retval = ioctl(jtag_fd, JTAG_SIOCFREQ, &jtag_freq); 79 | if (retval == -1) { 80 | perror("ioctl JTAG set freq fail!\n"); 81 | return -1; 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | int ast_set_jtag_trst(unsigned int active) 88 | { 89 | int retval; 90 | unsigned int trst_active = active; 91 | 92 | retval = ioctl(jtag_fd, JTAG_SIOCTRST, &trst_active); 93 | if (retval == -1) { 94 | perror("ioctl JTAG set trst fail!\n"); 95 | return -1; 96 | } 97 | return 0; 98 | } 99 | 100 | int ast_get_tap_state(enum jtag_tapstate* tap_state) 101 | { 102 | int retval; 103 | 104 | if (tap_state == NULL) 105 | return -1; 106 | retval = ioctl(jtag_fd, JTAG_GIOCSTATUS, tap_state); 107 | if (retval == -1) { 108 | perror("ioctl JTAG get tap state fail!\n"); 109 | return -1; 110 | } 111 | return 0; 112 | } 113 | 114 | int ast_jtag_run_test_idle(unsigned char end, unsigned int tck) 115 | { 116 | int retval; 117 | struct jtag_tap_state run_idle; 118 | __u8 execute_tck; 119 | 120 | do { 121 | execute_tck = tck > 0xff ? 0xff : tck; 122 | run_idle.from = JTAG_STATE_CURRENT; 123 | run_idle.reset = JTAG_NO_RESET; 124 | run_idle.endstate = end; 125 | run_idle.tck = execute_tck; 126 | 127 | ast_jtag_printf("from:%d, reset:%d, endstate:%d, tck:%d\n", 128 | run_idle.from, run_idle.reset, 129 | run_idle.endstate, run_idle.tck); 130 | 131 | retval = ioctl(jtag_fd, JTAG_SIOCSTATE, &run_idle); 132 | if (retval == -1) { 133 | perror("ioctl JTAG run reset fail!\n"); 134 | return -1; 135 | } 136 | tck -= execute_tck; 137 | } while (tck); 138 | 139 | // if(end) 140 | // usleep(3000); 141 | 142 | return 0; 143 | } 144 | 145 | int ast_jtag_xfer(unsigned char endsts, unsigned int len, const uint8_t *out, uint8_t *in, enum jtag_xfer_type type) 146 | { 147 | int retval; 148 | enum jtag_tapstate current_state; 149 | struct jtag_xfer xfer; 150 | unsigned int send_len_byte; 151 | 152 | ast_get_tap_state(¤t_state); 153 | xfer.type = type; 154 | xfer.direction = JTAG_READ_WRITE_XFER; 155 | xfer.from = current_state; 156 | xfer.endstate = endsts; 157 | xfer.padding = 0; 158 | xfer.length = len; 159 | xfer.tdio = (__u64)(uintptr_t)out; 160 | send_len_byte = DIV_ROUND_UP(xfer.length, BITS_PER_BYTE); 161 | 162 | #if DEBUG 163 | int i; 164 | for (i = 0; i < DIV_ROUND_UP(send_len_byte, 4); i++) 165 | ast_jtag_printf("tdo:%08x\n", out[i]); 166 | #endif 167 | retval = ioctl(jtag_fd, JTAG_IOCXFER, &xfer); 168 | if (retval == -1) { 169 | perror("ioctl JTAG sir fail!\n"); 170 | return -1; 171 | } 172 | memcpy(in, out, send_len_byte); 173 | #if DEBUG 174 | for (i = 0; i < DIV_ROUND_UP(send_len_byte, 4); i++) 175 | ast_jtag_printf("tdi:%08x\n",out[i]); 176 | #endif 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /svf/ast-jtag.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ */ 2 | /* 3 | * Copyright 2020 Aspeed Technology Inc. 4 | */ 5 | #include "stdint.h" 6 | typedef uint8_t __u8; 7 | typedef uint32_t __u32; 8 | typedef unsigned long long __u64; 9 | 10 | #include "jtag.h" 11 | 12 | #define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) 13 | #define BITS_PER_BYTE 8 14 | /******************************************************************************************************************/ 15 | int ast_jtag_open(char *dev); 16 | void ast_jtag_close(void); 17 | int ast_set_jtag_mode(uint8_t sw_mode); 18 | unsigned int ast_get_jtag_freq(void); 19 | int ast_set_jtag_freq(unsigned int freq); 20 | int ast_jtag_run_test_idle(unsigned char end, unsigned int tck); 21 | int ast_jtag_xfer(unsigned char endsts, unsigned int len, const uint8_t *out, 22 | uint8_t *in, enum jtag_xfer_type type); 23 | int ast_set_jtag_trst(unsigned int active); 24 | -------------------------------------------------------------------------------- /svf/jtag.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* Copyright (c) 2018 Mellanox Technologies. All rights reserved. */ 3 | /* Copyright (c) 2018 Oleksandr Shamray */ 4 | /* Copyright (c) 2019 Intel Corporation */ 5 | 6 | #ifndef __UAPI_LINUX_JTAG_H 7 | #define __UAPI_LINUX_JTAG_H 8 | 9 | /* 10 | * JTAG_XFER_MODE: JTAG transfer mode. Used to set JTAG controller transfer mode 11 | * This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE 12 | */ 13 | #define JTAG_XFER_MODE 0 14 | /* 15 | * JTAG_CONTROL_MODE: JTAG controller mode. Used to set JTAG controller mode 16 | * This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE 17 | */ 18 | #define JTAG_CONTROL_MODE 1 19 | /* 20 | * JTAG_MASTER_OUTPUT_DISABLE: JTAG master mode output disable, it is used to 21 | * enable other devices to own the JTAG bus. 22 | * This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE 23 | */ 24 | #define JTAG_MASTER_OUTPUT_DISABLE 0 25 | /* 26 | * JTAG_MASTER_MODE: JTAG master mode. Used to set JTAG controller master mode 27 | * This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE 28 | */ 29 | #define JTAG_MASTER_MODE 1 30 | /* 31 | * JTAG_XFER_HW_MODE: JTAG hardware mode. Used to set HW drived or bitbang 32 | * mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE 33 | */ 34 | #define JTAG_XFER_HW_MODE 1 35 | /* 36 | * JTAG_XFER_SW_MODE: JTAG software mode. Used to set SW drived or bitbang 37 | * mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE 38 | */ 39 | #define JTAG_XFER_SW_MODE 0 40 | 41 | /** 42 | * enum jtag_tapstate: 43 | * 44 | * @JTAG_STATE_TLRESET: JTAG state machine Test Logic Reset state 45 | * @JTAG_STATE_IDLE: JTAG state machine IDLE state 46 | * @JTAG_STATE_SELECTDR: JTAG state machine SELECT_DR state 47 | * @JTAG_STATE_CAPTUREDR: JTAG state machine CAPTURE_DR state 48 | * @JTAG_STATE_SHIFTDR: JTAG state machine SHIFT_DR state 49 | * @JTAG_STATE_EXIT1DR: JTAG state machine EXIT-1 DR state 50 | * @JTAG_STATE_PAUSEDR: JTAG state machine PAUSE_DR state 51 | * @JTAG_STATE_EXIT2DR: JTAG state machine EXIT-2 DR state 52 | * @JTAG_STATE_UPDATEDR: JTAG state machine UPDATE DR state 53 | * @JTAG_STATE_SELECTIR: JTAG state machine SELECT_IR state 54 | * @JTAG_STATE_CAPTUREIR: JTAG state machine CAPTURE_IR state 55 | * @JTAG_STATE_SHIFTIR: JTAG state machine SHIFT_IR state 56 | * @JTAG_STATE_EXIT1IR: JTAG state machine EXIT-1 IR state 57 | * @JTAG_STATE_PAUSEIR: JTAG state machine PAUSE_IR state 58 | * @JTAG_STATE_EXIT2IR: JTAG state machine EXIT-2 IR state 59 | * @JTAG_STATE_UPDATEIR: JTAG state machine UPDATE IR state 60 | * @JTAG_STATE_CURRENT: JTAG current state, saved by driver 61 | */ 62 | enum jtag_tapstate { 63 | JTAG_STATE_TLRESET, 64 | JTAG_STATE_IDLE, 65 | JTAG_STATE_SELECTDR, 66 | JTAG_STATE_CAPTUREDR, 67 | JTAG_STATE_SHIFTDR, 68 | JTAG_STATE_EXIT1DR, 69 | JTAG_STATE_PAUSEDR, 70 | JTAG_STATE_EXIT2DR, 71 | JTAG_STATE_UPDATEDR, 72 | JTAG_STATE_SELECTIR, 73 | JTAG_STATE_CAPTUREIR, 74 | JTAG_STATE_SHIFTIR, 75 | JTAG_STATE_EXIT1IR, 76 | JTAG_STATE_PAUSEIR, 77 | JTAG_STATE_EXIT2IR, 78 | JTAG_STATE_UPDATEIR, 79 | JTAG_STATE_CURRENT 80 | }; 81 | 82 | /** 83 | * enum jtag_reset: 84 | * 85 | * @JTAG_NO_RESET: JTAG run TAP from current state 86 | * @JTAG_FORCE_RESET: JTAG force TAP to reset state 87 | */ 88 | enum jtag_reset { 89 | JTAG_NO_RESET = 0, 90 | JTAG_FORCE_RESET = 1, 91 | }; 92 | 93 | /** 94 | * enum jtag_xfer_type: 95 | * 96 | * @JTAG_SIR_XFER: SIR transfer 97 | * @JTAG_SDR_XFER: SDR transfer 98 | */ 99 | enum jtag_xfer_type { 100 | JTAG_SIR_XFER = 0, 101 | JTAG_SDR_XFER = 1, 102 | }; 103 | 104 | /** 105 | * enum jtag_xfer_direction: 106 | * 107 | * @JTAG_READ_XFER: read transfer 108 | * @JTAG_WRITE_XFER: write transfer 109 | * @JTAG_READ_WRITE_XFER: read & write transfer 110 | */ 111 | enum jtag_xfer_direction { 112 | JTAG_READ_XFER = 1, 113 | JTAG_WRITE_XFER = 2, 114 | JTAG_READ_WRITE_XFER = 3, 115 | }; 116 | 117 | /** 118 | * struct jtag_tap_state - forces JTAG state machine to go into a TAPC 119 | * state 120 | * 121 | * @reset: 0 - run IDLE/PAUSE from current state 122 | * 1 - go through TEST_LOGIC/RESET state before IDLE/PAUSE 123 | * @end: completion flag 124 | * @tck: clock counter 125 | * 126 | * Structure provide interface to JTAG device for JTAG set state execution. 127 | */ 128 | struct jtag_tap_state { 129 | __u8 reset; 130 | __u8 from; 131 | __u8 endstate; 132 | __u8 tck; 133 | }; 134 | 135 | /** 136 | * union pad_config - Padding Configuration: 137 | * 138 | * @type: transfer type 139 | * @pre_pad_number: Number of prepadding bits bit[11:0] 140 | * @post_pad_number: Number of prepadding bits bit[23:12] 141 | * @pad_data : Bit value to be used by pre and post padding bit[24] 142 | * @int_value: unsigned int packed padding configuration value bit[32:0] 143 | * 144 | * Structure provide pre and post padding configuration in a single __u32 145 | */ 146 | union pad_config { 147 | struct { 148 | __u32 pre_pad_number : 12; 149 | __u32 post_pad_number : 12; 150 | __u32 pad_data : 1; 151 | __u32 rsvd : 7; 152 | }; 153 | __u32 int_value; 154 | }; 155 | 156 | /** 157 | * struct jtag_xfer - jtag xfer: 158 | * 159 | * @type: transfer type 160 | * @direction: xfer direction 161 | * @from: xfer current state 162 | * @endstate: xfer end state 163 | * @padding: xfer padding 164 | * @length: xfer bits length 165 | * @tdio : xfer data array 166 | * 167 | * Structure provide interface to JTAG device for JTAG SDR/SIR xfer execution. 168 | */ 169 | struct jtag_xfer { 170 | __u8 type; 171 | __u8 direction; 172 | __u8 from; 173 | __u8 endstate; 174 | __u32 padding; 175 | __u32 length; 176 | __u64 tdio; 177 | }; 178 | 179 | /** 180 | * struct bitbang_packet - jtag bitbang array packet: 181 | * 182 | * @data: JTAG Bitbang struct array pointer(input/output) 183 | * @length: array size (input) 184 | * 185 | * Structure provide interface to JTAG device for JTAG bitbang bundle execution 186 | */ 187 | struct bitbang_packet { 188 | struct tck_bitbang *data; 189 | __u32 length; 190 | } __attribute__((__packed__)); 191 | 192 | /** 193 | * struct jtag_bitbang - jtag bitbang: 194 | * 195 | * @tms: JTAG TMS 196 | * @tdi: JTAG TDI (input) 197 | * @tdo: JTAG TDO (output) 198 | * 199 | * Structure provide interface to JTAG device for JTAG bitbang execution. 200 | */ 201 | struct tck_bitbang { 202 | __u8 tms; 203 | __u8 tdi; 204 | __u8 tdo; 205 | } __attribute__((__packed__)); 206 | 207 | /** 208 | * struct jtag_mode - jtag mode: 209 | * 210 | * @feature: 0 - JTAG feature setting selector for JTAG controller HW/SW 211 | * 1 - JTAG feature setting selector for controller bus master 212 | * mode output (enable / disable). 213 | * @mode: (0 - SW / 1 - HW) for JTAG_XFER_MODE feature(0) 214 | * (0 - output disable / 1 - output enable) for JTAG_CONTROL_MODE 215 | * feature(1) 216 | * 217 | * Structure provide configuration modes to JTAG device. 218 | */ 219 | struct jtag_mode { 220 | __u32 feature; 221 | __u32 mode; 222 | }; 223 | 224 | /* ioctl interface */ 225 | #define __JTAG_IOCTL_MAGIC 0xb2 226 | 227 | #define JTAG_SIOCSTATE _IOW(__JTAG_IOCTL_MAGIC, 0, struct jtag_tap_state) 228 | #define JTAG_SIOCFREQ _IOW(__JTAG_IOCTL_MAGIC, 1, unsigned int) 229 | #define JTAG_GIOCFREQ _IOR(__JTAG_IOCTL_MAGIC, 2, unsigned int) 230 | #define JTAG_IOCXFER _IOWR(__JTAG_IOCTL_MAGIC, 3, struct jtag_xfer) 231 | #define JTAG_GIOCSTATUS _IOWR(__JTAG_IOCTL_MAGIC, 4, enum jtag_tapstate) 232 | #define JTAG_SIOCMODE _IOW(__JTAG_IOCTL_MAGIC, 5, unsigned int) 233 | #define JTAG_IOCBITBANG _IOW(__JTAG_IOCTL_MAGIC, 6, unsigned int) 234 | #define JTAG_SIOCTRST _IOW(__JTAG_IOCTL_MAGIC, 7, unsigned int) 235 | 236 | 237 | /******************************************************************************************************************/ 238 | int ast_jtag_open(char *dev); 239 | void ast_jtag_close(void); 240 | unsigned int ast_get_jtag_freq(void); 241 | int ast_set_jtag_freq(unsigned int freq); 242 | int ast_jtag_run_test_idle(unsigned char end, unsigned int tck); 243 | int ast_jtag_xfer(unsigned char endsts, unsigned int len, const uint8_t *out, uint8_t *in, enum jtag_xfer_type type); 244 | 245 | #endif /* __UAPI_LINUX_JTAG_H */ 246 | -------------------------------------------------------------------------------- /svf/main.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0+ 2 | /* 3 | * Copyright 2020 Aspeed Technology Inc. 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include "ast-jtag.h" 18 | #include "svf.h" 19 | 20 | #define ERROR_OK (0) 21 | #define ERROR_NO_CONFIG_FILE (-2) 22 | #define ERROR_BUF_TOO_SMALL (-3) 23 | #define ERROR_FAIL (-4) 24 | #define ERROR_WAIT (-5) 25 | #define ERROR_TIMEOUT_REACHED (-6) 26 | 27 | enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; 28 | int loglevel = LOG_WARN; 29 | 30 | static void 31 | usage(FILE *fp, int argc, char **argv) 32 | { 33 | fprintf(fp, 34 | "Usage: %s [options]\n\n" 35 | "Options:\n" 36 | " -h | --help Print this message\n" 37 | " -d | --debug Set log level, default = 3\n" 38 | " -n | --node jtag device node\n" 39 | " -f | --frequency frequency\n" 40 | " -p | --play play SVF file\n" 41 | " -s | --software software mode\n" 42 | "", 43 | argv[0]); 44 | } 45 | 46 | static const char short_options [] = "hsd:n:f:p:"; 47 | 48 | 49 | 50 | static const struct option 51 | long_options [] = { 52 | { "help", no_argument, NULL, 'h' }, 53 | { "debug", required_argument, NULL, 'd' }, 54 | { "node", required_argument, NULL, 'n' }, 55 | { "fequency", required_argument, NULL, 'f' }, 56 | { "play", required_argument, NULL, 'p' }, 57 | { "software", no_argument, NULL, 's' }, 58 | { 0, 0, 0, 0 } 59 | }; 60 | 61 | /*********************************************************************************/ 62 | 63 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 64 | 65 | 66 | /*************************************************************************************/ 67 | int main(int argc, char *argv[]) 68 | { 69 | int ret; 70 | char option; 71 | char svf_name[100] = ""; 72 | char dev_name[100] = ""; 73 | int svf = 0; 74 | unsigned int freq = 0; 75 | unsigned int jtag_freq = 0; 76 | uint8_t sw_mode = 0; 77 | 78 | while ((option = getopt_long(argc, argv, short_options, long_options, NULL)) != (char) -1) { 79 | switch (option) { 80 | case 'h': 81 | usage(stdout, argc, argv); 82 | exit(EXIT_SUCCESS); 83 | break; 84 | case 'd': 85 | loglevel = atol(optarg); 86 | printf("loglevel %d\n", loglevel); 87 | break; 88 | case 'n': 89 | strcpy(dev_name, optarg); 90 | if (!strcmp(dev_name, "")) { 91 | printf("No dev file name!\n"); 92 | usage(stdout, argc, argv); 93 | exit(EXIT_FAILURE); 94 | } 95 | break; 96 | case 'f': 97 | freq = atol(optarg); 98 | printf("frequency %d\n", freq); 99 | break; 100 | case 'p': 101 | svf = 1; 102 | strcpy(svf_name, optarg); 103 | if (!strcmp(svf_name, "")) { 104 | printf("No out file name!\n"); 105 | usage(stdout, argc, argv); 106 | exit(EXIT_FAILURE); 107 | } 108 | break; 109 | case 's': 110 | sw_mode = 1; 111 | break; 112 | default: 113 | usage(stdout, argc, argv); 114 | exit(EXIT_FAILURE); 115 | } 116 | } 117 | if (!svf){ 118 | usage(stdout, argc, argv); 119 | exit(EXIT_FAILURE); 120 | } 121 | 122 | if (ast_jtag_open(dev_name)) 123 | exit(1); 124 | 125 | ast_set_jtag_mode(sw_mode); 126 | //show current ast jtag configuration 127 | jtag_freq = ast_get_jtag_freq(); 128 | 129 | if (jtag_freq == 0) { 130 | perror("Jtag freq error !! \n"); 131 | goto out; 132 | } 133 | 134 | if (freq) { 135 | ast_set_jtag_freq(freq); 136 | printf("JTAG Set Freq %d\n", freq); 137 | } else { 138 | printf("JTAG Freq %d\n", jtag_freq); 139 | } 140 | 141 | if (svf) { 142 | printf("Playing %s \n", svf_name); 143 | ret = handle_svf_command(svf_name); 144 | if (ret == ERROR_OK) { 145 | printf("Success!\n"); 146 | } else { 147 | printf("Error: %d\n", ret); 148 | } 149 | } 150 | 151 | out: 152 | ast_jtag_close(); 153 | 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /svf/svf.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ */ 2 | /* 3 | * Copyright (C) 2005 by Dominic Rath 4 | * Dominic.Rath@gmx.de 5 | * 6 | * Copyright (C) 2007-2010 Øyvind Harboe 7 | * oyvind.harboe@zylin.com 8 | */ 9 | 10 | #ifndef SVF_H 11 | #define SVF_H 12 | 13 | #include 14 | 15 | /*------------------------------------------------------*/ 16 | 17 | /** 18 | * Defines JTAG Test Access Port states. 19 | * 20 | * These definitions were gleaned from the ARM7TDMI-S Technical 21 | * Reference Manual and validated against several other ARM core 22 | * technical manuals. 23 | * 24 | * FIXME some interfaces require specific numbers be used, as they 25 | * are handed-off directly to their hardware implementations. 26 | * Fix those drivers to map as appropriate ... then pick some 27 | * sane set of numbers here (where 0/uninitialized == INVALID). 28 | */ 29 | typedef enum tap_state { 30 | TAP_INVALID = -1, 31 | /* Proper ARM recommended numbers */ 32 | TAP_DREXIT2 = 0x0, 33 | TAP_DREXIT1 = 0x1, 34 | TAP_DRSHIFT = 0x2, 35 | TAP_DRPAUSE = 0x3, 36 | TAP_IRSELECT = 0x4, 37 | TAP_DRUPDATE = 0x5, 38 | TAP_DRCAPTURE = 0x6, 39 | TAP_DRSELECT = 0x7, 40 | TAP_IREXIT2 = 0x8, 41 | TAP_IREXIT1 = 0x9, 42 | TAP_IRSHIFT = 0xa, 43 | TAP_IRPAUSE = 0xb, 44 | TAP_IDLE = 0xc, 45 | TAP_IRUPDATE = 0xd, 46 | TAP_IRCAPTURE = 0xe, 47 | TAP_RESET = 0x0f, 48 | } tap_state_t; 49 | 50 | /** 51 | * Defines arguments for reset functions 52 | */ 53 | #define SRST_DEASSERT 0 54 | #define SRST_ASSERT 1 55 | #define TRST_DEASSERT 0 56 | #define TRST_ASSERT 1 57 | 58 | /** 59 | * Function tap_state_name 60 | * Returns a string suitable for display representing the JTAG tap_state 61 | */ 62 | const char *tap_state_name(tap_state_t state); 63 | 64 | /** Provides user-friendly name lookup of TAP states. */ 65 | tap_state_t tap_state_by_name(const char *name); 66 | 67 | /** The current TAP state of the pending JTAG command queue. */ 68 | extern tap_state_t cmd_queue_cur_state; 69 | 70 | /** 71 | * This structure defines a single scan field in the scan. It provides 72 | * fields for the field's width and pointers to scan input and output 73 | * values. 74 | * 75 | * In addition, this structure includes a value and mask that is used by 76 | * jtag_add_dr_scan_check() to validate the value that was scanned out. 77 | */ 78 | struct scan_field { 79 | /** The number of bits this field specifies */ 80 | int num_bits; 81 | /** A pointer to value to be scanned into the device */ 82 | const uint8_t *out_value; 83 | /** A pointer to a 32-bit memory location for data scanned out */ 84 | uint8_t *in_value; 85 | 86 | /** The value used to check the data scanned out. */ 87 | uint8_t *check_value; 88 | /** The mask to go with check_value */ 89 | uint8_t *check_mask; 90 | }; 91 | 92 | int handle_svf_command(char *filename); 93 | #endif /* SVF_H */ 94 | -------------------------------------------------------------------------------- /usb/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CFLAGS += -Wall 8 | OBJS = hid_gadget_test.o 9 | EXE = hid_gadget_app 10 | 11 | CC = $(CROSS_COMPILE)gcc 12 | 13 | .c.o: 14 | $(CC) $(CFLAGS) -c $< 15 | 16 | $(EXE): $(OBJS) 17 | $(CC) $(CFLAGS) $(OBJS) -o $@ 18 | 19 | clean: 20 | rm -f $(EXE) $(OBJS) 21 | 22 | install: 23 | cp $(EXE) $(INSTALL_DIR) 24 | 25 | -------------------------------------------------------------------------------- /usb/hid_gadget_test.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright 2020 Aspeed Technology Inc. 4 | */ 5 | 6 | /* 7 | * ============================ 8 | * this test code is from 9 | * https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt 10 | * Send and receive HID reports 11 | * ============================ 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define BUF_LEN 512 25 | #define MAX_VALUE_COUNT (64) 26 | #define KEYBOARD (0) 27 | #define MOUSE (1) 28 | #define JOYSTICK (2) 29 | #define PAUSE_MS (200) // pause between each value 30 | 31 | //#define DEBUG 32 | 33 | struct options { 34 | const char *opt; 35 | unsigned char val; 36 | }; 37 | 38 | static struct options kmod[] = { 39 | {.opt = "--left-ctrl", .val = 0x01}, 40 | {.opt = "--right-ctrl", .val = 0x10}, 41 | {.opt = "--left-shift", .val = 0x02}, 42 | {.opt = "--right-shift", .val = 0x20}, 43 | {.opt = "--left-alt", .val = 0x04}, 44 | {.opt = "--right-alt", .val = 0x40}, 45 | {.opt = "--left-meta", .val = 0x08}, 46 | {.opt = "--right-meta", .val = 0x80}, 47 | {.opt = NULL} 48 | }; 49 | 50 | static struct options kval[] = { 51 | {.opt = "--return", .val = 0x28}, 52 | {.opt = "--esc", .val = 0x29}, 53 | {.opt = "--bckspc", .val = 0x2a}, 54 | {.opt = "--tab", .val = 0x2b}, 55 | {.opt = "--spacebar", .val = 0x2c}, 56 | {.opt = "--caps-lock", .val = 0x39}, 57 | {.opt = "--f1", .val = 0x3a}, 58 | {.opt = "--f2", .val = 0x3b}, 59 | {.opt = "--f3", .val = 0x3c}, 60 | {.opt = "--f4", .val = 0x3d}, 61 | {.opt = "--f5", .val = 0x3e}, 62 | {.opt = "--f6", .val = 0x3f}, 63 | {.opt = "--f7", .val = 0x40}, 64 | {.opt = "--f8", .val = 0x41}, 65 | {.opt = "--f9", .val = 0x42}, 66 | {.opt = "--f10", .val = 0x43}, 67 | {.opt = "--f11", .val = 0x44}, 68 | {.opt = "--f12", .val = 0x45}, 69 | {.opt = "--insert", .val = 0x49}, 70 | {.opt = "--home", .val = 0x4a}, 71 | {.opt = "--pageup", .val = 0x4b}, 72 | {.opt = "--del", .val = 0x4c}, 73 | {.opt = "--end", .val = 0x4d}, 74 | {.opt = "--pagedown", .val = 0x4e}, 75 | {.opt = "--right", .val = 0x4f}, 76 | {.opt = "--left", .val = 0x50}, 77 | {.opt = "--down", .val = 0x51}, 78 | {.opt = "--kp-enter", .val = 0x58}, 79 | {.opt = "--up", .val = 0x52}, 80 | {.opt = "--num-lock", .val = 0x53}, 81 | {.opt = NULL} 82 | }; 83 | 84 | int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold) 85 | { 86 | char *tok = strtok(buf, " "); 87 | int key = 0; 88 | int i = 0; 89 | 90 | for (; tok != NULL; tok = strtok(NULL, " ")) { 91 | 92 | if (strcmp(tok, "--quit") == 0) 93 | return -1; 94 | 95 | if (strcmp(tok, "--hold") == 0) { 96 | *hold = 1; 97 | continue; 98 | } 99 | 100 | if (key < 6) { 101 | for (i = 0; kval[i].opt != NULL; i++) 102 | if (strcmp(tok, kval[i].opt) == 0) { 103 | report[2 + key++] = kval[i].val; 104 | break; 105 | } 106 | if (kval[i].opt != NULL) 107 | continue; 108 | } 109 | 110 | if (key < 6) 111 | if (islower(tok[0])) { 112 | report[2 + key++] = (tok[0] - ('a' - 0x04)); 113 | continue; 114 | } 115 | 116 | for (i = 0; kmod[i].opt != NULL; i++) 117 | if (strcmp(tok, kmod[i].opt) == 0) { 118 | report[0] = report[0] | kmod[i].val; 119 | break; 120 | } 121 | if (kmod[i].opt != NULL) 122 | continue; 123 | 124 | if (key < 6) 125 | fprintf(stderr, "unknown option: %s\n", tok); 126 | } 127 | 128 | return 8; 129 | } 130 | 131 | static struct options mmod[] = { 132 | {.opt = "--b1", .val = 0x01}, 133 | {.opt = "--b2", .val = 0x02}, 134 | {.opt = "--b3", .val = 0x04}, 135 | {.opt = NULL} 136 | }; 137 | 138 | int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold) 139 | { 140 | char *tok = strtok(buf, " "); 141 | int mvt = 0; 142 | int i = 0; 143 | int val; 144 | 145 | for (; tok != NULL; tok = strtok(NULL, " ")) { 146 | 147 | if (strcmp(tok, "--quit") == 0) 148 | return -1; 149 | 150 | if (strcmp(tok, "--hold") == 0) { 151 | *hold = 1; 152 | continue; 153 | } 154 | 155 | for (i = 0; mmod[i].opt != NULL; i++) 156 | if (strcmp(tok, mmod[i].opt) == 0) { 157 | report[0] = report[0] | mmod[i].val; 158 | break; 159 | } 160 | 161 | if (mmod[i].opt != NULL) 162 | continue; 163 | 164 | if (!(tok[0] == '-' && tok[1] == '-') && mvt < 4) { 165 | errno = 0; 166 | val = atoi(tok); 167 | report[4 + mvt++] = (char)(val & 0xff); 168 | report[4 + mvt++] = (char)((val >> 8) & 0xff); 169 | 170 | if (errno != 0) { 171 | fprintf(stderr, "Bad value:'%s'\n", tok); 172 | mvt -= 2; 173 | report[4 + mvt] = 0; 174 | } 175 | 176 | continue; 177 | } 178 | 179 | fprintf(stderr, "unknown option: %s\n", tok); 180 | } 181 | 182 | #ifdef DEBUG 183 | printf("report[0~7]: "); 184 | for (i = 0; i < 8; i++) 185 | printf("0x%x ", report[i]); 186 | 187 | printf("\n"); 188 | #endif 189 | 190 | return 8; 191 | } 192 | 193 | static struct options jmod[] = { 194 | {.opt = "--b1", .val = 0x10}, 195 | {.opt = "--b2", .val = 0x20}, 196 | {.opt = "--b3", .val = 0x40}, 197 | {.opt = "--b4", .val = 0x80}, 198 | {.opt = "--hat1", .val = 0x00}, 199 | {.opt = "--hat2", .val = 0x01}, 200 | {.opt = "--hat3", .val = 0x02}, 201 | {.opt = "--hat4", .val = 0x03}, 202 | {.opt = "--hatneutral", .val = 0x04}, 203 | {.opt = NULL} 204 | }; 205 | 206 | int joystick_fill_report(char report[8], char buf[BUF_LEN], int *hold) 207 | { 208 | char *tok = strtok(buf, " "); 209 | int mvt = 0; 210 | int i = 0; 211 | 212 | *hold = 1; 213 | 214 | /* set default hat position: neutral */ 215 | report[3] = 0x04; 216 | 217 | for (; tok != NULL; tok = strtok(NULL, " ")) { 218 | 219 | if (strcmp(tok, "--quit") == 0) 220 | return -1; 221 | 222 | for (i = 0; jmod[i].opt != NULL; i++) 223 | if (strcmp(tok, jmod[i].opt) == 0) { 224 | report[3] = (report[3] & 0xF0) | jmod[i].val; 225 | break; 226 | } 227 | if (jmod[i].opt != NULL) 228 | continue; 229 | 230 | if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) { 231 | errno = 0; 232 | report[mvt++] = (char)strtol(tok, NULL, 0); 233 | if (errno != 0) { 234 | fprintf(stderr, "Bad value:'%s'\n", tok); 235 | report[mvt--] = 0; 236 | } 237 | continue; 238 | } 239 | 240 | fprintf(stderr, "unknown option: %s\n", tok); 241 | } 242 | return 4; 243 | } 244 | 245 | void print_options(char c) 246 | { 247 | int i = 0; 248 | 249 | if (c == 'k') { 250 | printf(" keyboard options:\n" 251 | " --hold\n"); 252 | for (i = 0; kmod[i].opt != NULL; i++) 253 | printf("\t\t%s\n", kmod[i].opt); 254 | printf("\n keyboard values:\n" 255 | " [a-z] or\n"); 256 | for (i = 0; kval[i].opt != NULL; i++) 257 | printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : ""); 258 | printf("\n"); 259 | } else if (c == 'm') { 260 | printf(" mouse options:\n" 261 | " --hold\n"); 262 | for (i = 0; mmod[i].opt != NULL; i++) 263 | printf("\t\t%s\n", mmod[i].opt); 264 | printf("\n mouse values:\n" 265 | " Two signed numbers\n" 266 | "--quit to close\n"); 267 | } else { 268 | printf(" joystick options:\n"); 269 | for (i = 0; jmod[i].opt != NULL; i++) 270 | printf("\t\t%s\n", jmod[i].opt); 271 | printf("\n joystick values:\n" 272 | " three signed numbers\n" 273 | "--quit to close\n"); 274 | } 275 | } 276 | 277 | void commandLineUsage(void) 278 | { 279 | printf("\n=============================================================================\n"); 280 | printf("\tUsage: hid_gadget_test devname mouse|keyboard|joystick [inputFile N]\n\n"); 281 | printf("\tOption: inputFile N:\n"); 282 | printf("\t\tinputFile - keyboard or mouse values (max 64 values) separated by newline.\n"); 283 | printf("\t\tN - times to run the values, 0 - run it till you stop this test\n"); 284 | printf("\t\te.g:\n"); 285 | printf("\t\t==interactive== hid_gadget_test /dev/hidg0 keyboard\n"); 286 | printf("=============================================================================\n\n"); 287 | } 288 | 289 | int main(int argc, const char *argv[]) 290 | { 291 | const char *filename = NULL; 292 | int fd = 0; 293 | int fd_input = 0; 294 | char buf[BUF_LEN]; 295 | int cmd_len; 296 | char report[8]; 297 | int to_send = 8; 298 | int hold = 0; 299 | fd_set rfds; 300 | int retval, i; 301 | 302 | commandLineUsage(); 303 | 304 | if (argc < 3) { 305 | fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n", argv[0]); 306 | return 1; 307 | } 308 | 309 | if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j') 310 | return 2; 311 | 312 | filename = argv[1]; 313 | 314 | fd = open(filename, O_RDWR, 0666); 315 | if (fd == -1) { 316 | perror(filename); 317 | return 3; 318 | } 319 | 320 | if (argc == 3) { 321 | // get user input 322 | print_options(argv[2][0]); 323 | 324 | while (1) { 325 | FD_ZERO(&rfds); 326 | FD_SET(STDIN_FILENO, &rfds); 327 | FD_SET(fd, &rfds); 328 | 329 | retval = select(fd + 1, &rfds, NULL, NULL, NULL); 330 | if (retval == -1 && errno == EINTR) 331 | continue; 332 | if (retval < 0) { 333 | perror("select()"); 334 | return 4; 335 | } 336 | 337 | if (FD_ISSET(fd, &rfds)) { 338 | cmd_len = read(fd, buf, BUF_LEN - 1); 339 | printf("recv report:"); 340 | for (i = 0; i < cmd_len; i++) 341 | printf(" %02x", buf[i]); 342 | printf("\n"); 343 | } 344 | 345 | if (FD_ISSET(STDIN_FILENO, &rfds)) { 346 | memset(report, 0x0, sizeof(report)); 347 | cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1); 348 | 349 | if (cmd_len == 0) 350 | break; 351 | 352 | buf[cmd_len - 1] = '\0'; 353 | hold = 0; 354 | 355 | memset(report, 0x0, sizeof(report)); 356 | if (argv[2][0] == 'k') 357 | to_send = keyboard_fill_report(report, buf, &hold); 358 | else if (argv[2][0] == 'm') 359 | to_send = mouse_fill_report(report, buf, &hold); 360 | else 361 | to_send = joystick_fill_report(report, buf, &hold); 362 | 363 | if (to_send == -1) 364 | break; 365 | 366 | if (write(fd, report, to_send) != to_send) { 367 | perror(filename); 368 | return 5; 369 | } 370 | if (!hold) { 371 | memset(report, 0x0, sizeof(report)); 372 | if (write(fd, report, to_send) != to_send) { 373 | perror(filename); 374 | return 6; 375 | } 376 | } 377 | } 378 | } // while 379 | } 380 | 381 | close(fd); 382 | if (fd_input) 383 | close(fd_input); 384 | 385 | return 0; 386 | 387 | } 388 | -------------------------------------------------------------------------------- /video/Makefile: -------------------------------------------------------------------------------- 1 | ifdef INST 2 | ifeq ("$(origin INST)", "command line") 3 | INSTALL_DIR := $(INST) 4 | endif 5 | endif 6 | 7 | CFLAGS += -Wall -O3 8 | CXXFLAGS+= -Wall -O3 9 | OBJS = main.o main1.o main2.o video.o ikvm_video.o bmp.o 10 | EXE = ast-video 11 | 12 | CC = $(CROSS_COMPILE)g++ 13 | CXX = $(CROSS_COMPILE)g++ 14 | 15 | .c.o: 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | $(EXE): $(OBJS) 19 | $(CC) $(CFLAGS) $(OBJS) -o $@ 20 | 21 | clean: 22 | rm -f $(EXE) $(OBJS) 23 | 24 | install: 25 | cp $(EXE) $(INSTALL_DIR) 26 | cp video.inf $(INSTALL_DIR) 27 | -------------------------------------------------------------------------------- /video/bmp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-2-Clause */ 2 | #ifndef BMP_H_INCLUDED 3 | #define BMP_H_INCLUDED 4 | 5 | int loadBMP(const char *filename, unsigned char *pixels, int *width, int *height); 6 | int writeBMP(const char *filename, unsigned char *data, int width, int height); 7 | 8 | #endif /* BMP_H_INCLUDED */ 9 | -------------------------------------------------------------------------------- /video/ikvm_video.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define pr_dbg(fmt, args...) printf("%s(): " fmt, __func__, ## args) 12 | #define V4L2_PIX_FMT_AJPG v4l2_fourcc('A', 'J', 'P', 'G') 13 | #define V4L2_PIX_FMT_FLAG_PARTIAL_JPG 0x00000004 14 | 15 | namespace ikvm 16 | { 17 | 18 | /* 19 | * @class Video 20 | * @brief Sets up the V4L2 video device and performs read operations 21 | */ 22 | class Video 23 | { 24 | public: 25 | /* 26 | * @brief Constructs Video object 27 | * 28 | * @param[in] p - Path to the V4L2 video device 29 | * @param[in] fr - desired frame rate of the video 30 | */ 31 | Video(int i = 0, int fr = 30, int q = 4, int sub = 0, int fmt = 0); 32 | ~Video(); 33 | Video(const Video&) = default; 34 | Video& operator=(const Video&) = default; 35 | Video(Video&&) = default; 36 | Video& operator=(Video&&) = default; 37 | 38 | /* 39 | * @brief Gets the video frame data 40 | * 41 | * @return Pointer to the video frame data 42 | */ 43 | char* getData(); 44 | /* @brief Performs read to grab latest video frame */ 45 | int getFrame(); 46 | /* 47 | * @brief Gets whether or not the video frame needs to be resized 48 | * 49 | * @return Boolean indicating if the frame needs to be resized 50 | */ 51 | bool needsResize(); 52 | /* @brief Performs the resize and re-allocates framebuffer */ 53 | int resize(); 54 | /* @brief Starts streaming from the video device */ 55 | int start(); 56 | /* @brief Stops streaming from the video device */ 57 | int stop(); 58 | /* @brief Restarts streaming from the video device */ 59 | int restart() 60 | { 61 | stop(); 62 | return start(); 63 | } 64 | /* @brief set the input of the video to capture */ 65 | void setInput(int input); 66 | /* @brief set the size of input, aspeed test only */ 67 | void setInputSize(int width, int height); 68 | /* @brief get input buffer address of the video, aspeed test only */ 69 | void getInputBuffer(unsigned char **addr); 70 | /* @brief trigger capture, aspeed test only */ 71 | void capture(); 72 | 73 | /* 74 | * @brief Gets the desired video frame rate in frames per second 75 | * 76 | * @return Value of the desired frame rate 77 | */ 78 | inline int getFrameRate() const 79 | { 80 | return frameRate; 81 | } 82 | inline void setFrameRate(int fr) 83 | { 84 | frameRate = fr; 85 | } 86 | /* 87 | * @brief Gets the size of the video frame data 88 | * 89 | * @return Value of the size of the video frame data in bytes 90 | */ 91 | inline size_t getFrameSize() const 92 | { 93 | return buffers[lastFrameIndex].payload; 94 | } 95 | /* 96 | * @brief Gets the height of the video frame 97 | * 98 | * @return Value of the height of video frame in lines 99 | */ 100 | inline size_t getHeight() const 101 | { 102 | return height; 103 | } 104 | /* 105 | * @brief Gets the width of the video frame 106 | * 107 | * @return Value of the width of video frame in pixels 108 | */ 109 | inline size_t getWidth() const 110 | { 111 | return width; 112 | } 113 | /* 114 | * @brief Gets the video frame count in sequence 115 | * 116 | * @return Value of video frame count in sequence 117 | */ 118 | inline size_t getFrameNumber() const 119 | { 120 | return buffers[lastFrameIndex].sequence; 121 | } 122 | /* 123 | * @brief Gets the quality of the video frame 124 | * 125 | * @return Value of the quality of video frame 126 | */ 127 | inline int getQuality() const 128 | { 129 | return jpegQuality; 130 | } 131 | /* 132 | * @brief Sets the jpeg format of the video frame 133 | * 134 | */ 135 | inline void setQuality(int _quality) 136 | { 137 | jpegQuality = _quality; 138 | } 139 | /* 140 | * @brief Gets the subsampling of the video frame 141 | * 142 | * @return Value of the subsampling of video frame, 1:420/0:444 143 | */ 144 | inline int getSubsampling() const 145 | { 146 | return jpegSubSampling; 147 | } 148 | /* 149 | * @brief Sets the subsampling of the video frame 150 | * 151 | */ 152 | inline void setSubsampling(int _sub) 153 | { 154 | jpegSubSampling = _sub; 155 | } 156 | /* 157 | * @brief Gets the jpeg format of the video frame 158 | * 159 | * @return Value of the jpeg format of video frame 160 | * 0:standard jpeg, 1:aspeed, 2:partial 161 | */ 162 | inline int getFormat() const 163 | { 164 | return format; 165 | } 166 | /* 167 | * @brief Sets the jpeg format of the video frame 168 | * 169 | */ 170 | inline void setFormat(int _fmt) 171 | { 172 | format = _fmt; 173 | } 174 | /* 175 | * @brief Gets the HQ Mode of compression 176 | * 177 | * @return Value of the HQ Mode 178 | */ 179 | inline bool getHQMode() const 180 | { 181 | return aspeedHQMode; 182 | } 183 | /* 184 | * @brief Sets the HQ Mode of compression 185 | * 186 | */ 187 | inline void setHQMode(bool mode) 188 | { 189 | aspeedHQMode= mode; 190 | } 191 | /* 192 | * @brief Gets the hq quality of the video frame 193 | * 194 | * @return Value of the quality of video frame 195 | */ 196 | inline int getHQuality() const 197 | { 198 | return aspeedHQuality; 199 | } 200 | /* 201 | * @brief Sets the jpeg format of the video frame 202 | * 203 | */ 204 | inline void setHQuality(int _quality) 205 | { 206 | aspeedHQuality = _quality; 207 | } 208 | 209 | inline void setID(int _id) 210 | { 211 | instId = _id; 212 | } 213 | 214 | private: 215 | /* 216 | * @brief find v4l2 ctrl-id by the given name 217 | * 218 | * @param[in] name - v4l2 ctrl name 219 | * @return v4l2 ctrl-id if found, but 0 if not found. 220 | */ 221 | int common_find_ctrl_id(const char *name); 222 | 223 | /* 224 | * @struct Buffer 225 | * @brief Store the address and size of frame data from streaming 226 | * operations 227 | */ 228 | struct Buffer 229 | { 230 | Buffer() : data(nullptr), queued(false), payload(0), size(0) 231 | { 232 | } 233 | ~Buffer() = default; 234 | Buffer(const Buffer&) = default; 235 | Buffer& operator=(const Buffer&) = default; 236 | Buffer(Buffer&&) = default; 237 | Buffer& operator=(Buffer&&) = default; 238 | 239 | void* data; 240 | bool queued; 241 | size_t payload; 242 | size_t size; 243 | uint32_t sequence; 244 | }; 245 | 246 | int instId; 247 | /* 248 | * @brief Boolean to indicate whether the resize was triggered during 249 | * the open operation 250 | */ 251 | bool resizeAfterOpen; 252 | /* @brief Indicates whether or not timings query was last sucessful */ 253 | bool timingsError; 254 | /* @brief File descriptor for the V4L2 video device */ 255 | int fd; 256 | /* @brief Desired frame rate of video stream in frames per second */ 257 | int frameRate; 258 | /* @brief Buffer index for the last video frame */ 259 | int lastFrameIndex; 260 | /* @brief Height in lines of the video frame */ 261 | size_t height; 262 | /* @brief Width in pixels of the video frame */ 263 | size_t width; 264 | /* @brief jpeg's quality (0~11) */ 265 | int jpegQuality; 266 | /* @brief jpeg's subsampling, 1:420/0:444 */ 267 | int jpegSubSampling; 268 | /* @brief aspeed's jpeg format, which support partial update */ 269 | int format; 270 | /* @brief aspeed's hq mode, only for 444 subsampling 271 | * It can have better quality for static video by 2-pass video compression scheme 272 | */ 273 | bool aspeedHQMode; 274 | /* @brief aspeed's hq quality, (1~12) 275 | */ 276 | bool aspeedHQuality; 277 | /* @brief Streaming buffer storage */ 278 | std::vector buffers; 279 | /* @brief map of ctrl and its name */ 280 | std::map ctrl_str2q; 281 | /* @brief input of the capture. 0: vga, 1:gfx, 2:memory */ 282 | int input; 283 | /* @brief Width in pixels of the dbg video frame from memory, only useful if input is 2 */ 284 | size_t dbg_width; 285 | /* @brief Height in lines of the dbg video frame from memory, only useful if input is 2 */ 286 | size_t dbg_height; 287 | }; 288 | 289 | } // namespace ikvm 290 | -------------------------------------------------------------------------------- /video/main.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | // Copyright (C) 2021 Aspeed Technology Inc. 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define PORT 1234 18 | 19 | extern int main_v1(); 20 | extern int main_v2(int argc, char **argv); 21 | 22 | int connfd; 23 | unsigned long *buffer; 24 | 25 | int net_setup(void) 26 | { 27 | struct sockaddr_in addr_svr; 28 | struct sockaddr_in addr_cln; 29 | socklen_t sLen = sizeof(addr_cln); 30 | 31 | int sockfd; 32 | int sndbuf = 0x100000; 33 | 34 | buffer = (unsigned long *)malloc (1024); 35 | 36 | bzero(&addr_svr, sizeof(addr_svr)); 37 | addr_svr.sin_family= AF_INET; 38 | addr_svr.sin_port= htons(PORT); 39 | addr_svr.sin_addr.s_addr = INADDR_ANY; 40 | 41 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 42 | if( sockfd == -1){ 43 | perror("call socket \n"); 44 | return -1; 45 | } 46 | 47 | setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, 0x100000); 48 | 49 | //bind 50 | if (bind(sockfd, (struct sockaddr *)&addr_svr, sizeof(addr_svr)) == -1) { 51 | perror("call bind \n"); 52 | return -1; 53 | } 54 | 55 | //listen 56 | if (listen(sockfd, 10) == -1) { 57 | perror("call listen \n"); 58 | return -1; 59 | } 60 | 61 | printf("Accepting connections ...\n"); 62 | 63 | connfd = accept(sockfd, (struct sockaddr *)&addr_cln, &sLen); 64 | if (connfd == -1) { 65 | perror("call accept\n"); 66 | return -1; 67 | } 68 | 69 | printf("Client connect ...\n"); 70 | return 0; 71 | } 72 | 73 | /* get_driver_version: get the driver version 74 | * return 0: ast-video, 1: aspeed-video, ow: no available driver 75 | */ 76 | int get_driver_version(void) 77 | { 78 | int fd; 79 | 80 | fd = open("/dev/ast-video", O_RDWR); 81 | if (fd != -1) { 82 | close(fd); 83 | return 1; 84 | } 85 | 86 | fd = open("/dev/video0", O_RDWR); 87 | if (fd != -1) { 88 | close(fd); 89 | return 2; 90 | } 91 | 92 | return -1; 93 | } 94 | 95 | int main(int argc, char **argv) { 96 | int v = get_driver_version(); 97 | 98 | if (v == -1) { 99 | perror("no video device available\n"); 100 | return -1; 101 | } 102 | 103 | printf("App works for aspeed video driver v%d\n\n", v); 104 | if (v == 1) 105 | return main_v1(); 106 | 107 | return main_v2(argc, argv); 108 | } 109 | -------------------------------------------------------------------------------- /video/main2.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | // Copyright (C) 2021 Aspeed Technology Inc. 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include "ikvm_video.hpp" 16 | #include "regs-video.h" 17 | #include "bmp.h" 18 | 19 | #define JPEG_DATA_OFFSET 0x50 20 | 21 | static const char opt_short [] = "c:shq:p:a:m:f:t:i:"; 22 | static const struct option opt_long [] = { 23 | { "capture", required_argument, NULL, 'c' }, 24 | { "stream", no_argument, NULL, 's' }, 25 | { "help", no_argument, NULL, 'h' }, 26 | { "quality", required_argument, NULL, 'q' }, 27 | { "subsample", required_argument, NULL, 'p' }, 28 | { "aspeed_fmt", required_argument, NULL, 'a' }, 29 | { "HQmode", required_argument, NULL, 'm' }, 30 | { "fps", required_argument, NULL, 'f' }, 31 | { "test", required_argument, NULL, 't' }, 32 | { "instance", required_argument, NULL, 'i' }, 33 | { 0, 0, 0, 0 } 34 | }; 35 | 36 | static size_t width, height; 37 | 38 | extern int connfd; 39 | extern unsigned long *buffer; 40 | extern int net_setup(void); 41 | 42 | static void print_usage(FILE *fp, int argc, char **argv) 43 | { 44 | fprintf(fp, 45 | "Usage:\n" 46 | " %s [OPTION]\n" 47 | "\n" 48 | "Options:\n" 49 | " -h | --help Print this message\n" 50 | " -c | --capture capture few frames\n" 51 | " -s | --stream streaming to network\n" 52 | " -q | --quality assign 0~11 jpeg quality\n" 53 | " -p | --subsample 420/444 jpeg subsampling\n" 54 | " -a | --aspeed_fmt 0 for standard jpeg; 1 for aspeed jpeg mode; 2 for partial jpeg\n" 55 | " -m | --HQmode enable HQ mode\n" 56 | " -f | --fps 0 for no control; o/w new-fps = org-fps*fps/60 \n" 57 | " -t | --test 0 stop/run test;\n" 58 | " -i | --instance device to run;\n" 59 | "\n", 60 | argv[0] 61 | ); 62 | } 63 | 64 | static void save2file(char *data, size_t size, const char *fileName) 65 | { 66 | int fd = open(fileName, O_CREAT | O_WRONLY, 0644); 67 | 68 | if (fd < 0) { 69 | printf("%s file open failed\n", fileName); 70 | return; 71 | } 72 | 73 | if (write(fd, data, size) < 0) { 74 | printf("%s file write failed\n", fileName); 75 | } 76 | printf("Save to %s, size %zu\n", fileName, size); 77 | close(fd); 78 | } 79 | 80 | static void loadFile(char *data, size_t size, const char *fileName) 81 | { 82 | int fd = open(fileName, O_RDONLY); 83 | 84 | if (fd < 0) { 85 | printf("%s file open failed\n", fileName); 86 | return; 87 | } 88 | 89 | if (read(fd, data, size) < 0) { 90 | printf("%s file write failed\n", fileName); 91 | } 92 | close(fd); 93 | } 94 | 95 | static void transfer(ikvm::Video *v, unsigned char *socketbuffer) 96 | { 97 | uint32_t count; 98 | uint32_t send_len; 99 | TRANSFER_HEADER Transfer_Header; 100 | bool firstframe; 101 | char* data = v->getData(); 102 | 103 | if (data == nullptr) 104 | return; 105 | 106 | if (width == v->getWidth() && height == v->getHeight()) { 107 | firstframe = false; 108 | } else { 109 | firstframe = true; 110 | width = v->getWidth(); 111 | height = v->getHeight(); 112 | } 113 | 114 | Transfer_Header.Data_Length = v->getFrameSize(); 115 | // Jammy: kvm sample no use? 116 | Transfer_Header.Blocks_Changed = 1; 117 | 118 | Transfer_Header.Frist_frame = firstframe; 119 | Transfer_Header.Compress_type = !v->getFormat(); 120 | 121 | // if (VideoEngineInfo->INFData.DownScalingEnable == 1) { 122 | // Transfer_Header.User_Width = VideoEngineInfo->DestinationModeInfo.X; 123 | // Transfer_Header.User_Height = VideoEngineInfo->DestinationModeInfo.Y; 124 | // } else { 125 | Transfer_Header.User_Width = v->getWidth(); 126 | Transfer_Header.User_Height = v->getHeight(); 127 | // } 128 | Transfer_Header.RC4_Enable = 0; 129 | Transfer_Header.Y_Table = v->getQuality(); 130 | Transfer_Header.Mode_420 = v->getSubsampling(); 131 | Transfer_Header.Direct_Mode = 0; 132 | //Add for fixing the auto mode and RC4 bug 133 | Transfer_Header.Advance_Table = v->getHQuality() - 1; 134 | Transfer_Header.Differential_Enable = 0; 135 | Transfer_Header.VQ_Mode = 0; 136 | 137 | //send host header 138 | send (connfd, &Transfer_Header, 29, MSG_WAITALL); 139 | //recv client header 140 | do { 141 | count = recv(connfd, buffer, 29, MSG_WAITALL); 142 | } while (count != 29); 143 | 144 | //send frame 145 | do { 146 | send_len = send(connfd, (unsigned char *)data, Transfer_Header.Data_Length, MSG_WAITALL); 147 | } while (send_len != Transfer_Header.Data_Length); 148 | 149 | do { 150 | count = recv (connfd, socketbuffer, 29, MSG_WAITALL); 151 | } while (count != 29); 152 | } 153 | 154 | static void test0(int times) 155 | { 156 | char data[0x200000]; 157 | size_t length; 158 | ikvm::Video *video; 159 | int count = 0; 160 | 161 | video = new ikvm::Video(); 162 | video->start(); 163 | video->getFrame(); 164 | if (video->getData() != nullptr) { 165 | length = video->getFrameSize(); 166 | memcpy(data, video->getData(), length); 167 | save2file(data, length, "golden.jpg"); 168 | } else { 169 | printf("%s failed at grab golden\n", __func__); 170 | return; 171 | } 172 | video->stop(); 173 | delete video; 174 | 175 | 176 | do { 177 | ++count; 178 | video = new ikvm::Video(); 179 | video->start(); 180 | video->getFrame(); 181 | if (video->getData() != nullptr) { 182 | if (length != video->getFrameSize()) { 183 | printf("%s failed at %d, length doesn't match(%zu<->%zu)\n", 184 | __func__, count, length, video->getFrameSize()); 185 | return; 186 | } 187 | // skip header whose timestamp would change 188 | if (memcmp(data + JPEG_DATA_OFFSET, video->getData() + JPEG_DATA_OFFSET, length - JPEG_DATA_OFFSET) != 0) { 189 | printf("%s failed at %d, data match\n", __func__, count); 190 | save2file(video->getData(), length, "fail.jpg"); 191 | return; 192 | } 193 | } else { 194 | printf("%s failed capture at %d\n", __func__, count); 195 | } 196 | video->stop(); 197 | delete video; 198 | } while (--times); 199 | } 200 | 201 | static void test1(ikvm::Video *v) 202 | { 203 | int rc = 0; 204 | int w, h; 205 | int bmp_w, bmp_h; 206 | unsigned char *buf = NULL; 207 | char data[0x200000]; 208 | int count = 1; 209 | char filename[32]; 210 | 211 | printf("In this test, it will load bmp, golden_#.bmp, for test.\n"); 212 | printf("Please switch video driver to input from memory by sysfs.\n"); 213 | printf("Please give the size of the bmp used.\n"); 214 | printf("width :"); 215 | scanf("%d", &w); 216 | printf("height :"); 217 | scanf("%d", &h); 218 | v->setInput(2); 219 | v->setInputSize(w, h); 220 | 221 | v->start(); 222 | v->getInputBuffer(&buf); 223 | if (buf == MAP_FAILED) 224 | return; 225 | 226 | printf("\n-----Test Start-----\n"); 227 | do { 228 | // prepare test data 229 | snprintf(filename, 32, "test_%d.bmp", count); 230 | if (loadBMP(filename, buf, &bmp_w, &bmp_h)) 231 | break; 232 | 233 | if (bmp_w != w || bmp_h != h) { 234 | rc = -1; 235 | printf("bmp size(%d * %d) isn't match\n", bmp_w, bmp_h); 236 | break; 237 | } 238 | 239 | // prepare golden data 240 | snprintf(filename, 32, "golden_%d.jpg", count); 241 | loadFile(data, 0x200000, filename); 242 | 243 | printf("*%3d: ", count); 244 | // single-step trigger 245 | v->capture(); 246 | if (v->getFrame() == 0) { 247 | if (memcmp(data + JPEG_DATA_OFFSET, v->getData() + JPEG_DATA_OFFSET, v->getFrameSize() - JPEG_DATA_OFFSET) != 0) { 248 | rc = -1; 249 | printf("NG, data mismatch\n"); 250 | snprintf(filename, 32, "fail_%d.jpg", count); 251 | save2file(v->getData(), v->getFrameSize(), filename); 252 | } else 253 | printf("OK\n"); 254 | } else { 255 | rc = -1; 256 | printf("NG, no new frame available\n"); 257 | break; 258 | } 259 | count++; 260 | } while(1); 261 | v->stop(); 262 | 263 | printf("\nTest Result: %s\n", rc ? "Fail" : "Pass"); 264 | } 265 | 266 | static void test(ikvm::Video *v, int cases) 267 | { 268 | if (cases == 0) { 269 | delete v; 270 | test0(100); 271 | } else if (cases == 1) { 272 | test1(v); 273 | } 274 | } 275 | 276 | static const char * const compress_mode_str[] = {"DCT Only", 277 | "DCT VQ mix 2-color", "DCT VQ mix 4-color"}; 278 | static const char * const format_str[] = {"Standard JPEG", 279 | "Aspeed JPEG", "Partial JPEG"}; 280 | 281 | int main_v2(int argc, char **argv) { 282 | 283 | char opt; 284 | uint32_t times = 0, quality = 0, fps = 0; 285 | bool is420 = false; 286 | int format = 0, id = 0; 287 | bool hq_enable = false; 288 | char *data; 289 | char fileName[32]; 290 | bool is_streaming = false; 291 | size_t frameNumber = 0; 292 | ikvm::Video *video; 293 | unsigned char *socketbuffer; 294 | 295 | video = new ikvm::Video(); 296 | while ((opt = getopt_long(argc, argv, opt_short, opt_long, NULL)) != (char) - 1) { 297 | switch (opt) { 298 | case 'm': 299 | hq_enable = strtoul(optarg, 0, 10); 300 | printf("aspeed HQ mode is %s\n", hq_enable ? "on" : "off"); 301 | video->setHQMode(hq_enable); 302 | break; 303 | case 'a': 304 | format = strtoul(optarg, 0, 10); 305 | printf("aspeed fmt is %s\n", format_str[format]); 306 | video->setFormat(format); 307 | break; 308 | case 'q': 309 | quality = strtoul(optarg, 0, 10); 310 | if (quality > 11) { 311 | printf("quality(%d) invalid (0~11). Use default 4.\n", 312 | quality); 313 | quality = 4; 314 | } 315 | printf("quality is %d\n", quality); 316 | video->setQuality(quality); 317 | break; 318 | case 'p': 319 | is420 = strncmp(optarg, "444", 3); 320 | printf("subsampling is %s\n", is420 ? "420" : "444"); 321 | video->setSubsampling(is420); 322 | break; 323 | case 'f': 324 | fps = strtoul(optarg, 0, 10); 325 | if (fps > 60) { 326 | fps = 60; 327 | } 328 | printf("fps is %d\n", fps); 329 | video->setFrameRate(fps); 330 | break; 331 | case 's': 332 | is_streaming = true; 333 | break; 334 | case 'c': 335 | times = strtoul(optarg, 0, 10); 336 | is_streaming = false; 337 | break; 338 | case 'h': 339 | print_usage(stdout, argc, argv); 340 | return 0; 341 | case 't': 342 | test(video, strtoul(optarg, 0, 10)); 343 | return 0; 344 | case 'i': 345 | id = strtoul(optarg, 0, 10); 346 | video->setID(id); 347 | break; 348 | default: 349 | print_usage(stdout, argc, argv); 350 | return -1; 351 | } 352 | } 353 | 354 | if (is_streaming) { 355 | if (net_setup() != 0) 356 | return -1; 357 | 358 | socketbuffer = (unsigned char*)malloc ((size_t) 1024); 359 | video->start(); 360 | while(1) { 361 | if (video->getFrame() == 0) { 362 | if ((video->getFrameNumber() != frameNumber + 1) && video->getFrameNumber()) 363 | printf("%s: discontinuous frame number (%zu -> %zu)\n", 364 | __func__, frameNumber, video->getFrameNumber()); 365 | 366 | frameNumber = video->getFrameNumber(); 367 | transfer(video, socketbuffer); 368 | } else 369 | pr_dbg("no new frame available\n"); 370 | 371 | if (video->needsResize()) 372 | { 373 | video->resize(); 374 | frameNumber = 0; 375 | } 376 | } 377 | video->stop(); 378 | free(socketbuffer); 379 | free(buffer); 380 | } else { 381 | uint8_t count = 0; 382 | 383 | video->start(); 384 | while (times--) { 385 | sprintf(fileName, "capture%d.jpg", ++count); 386 | 387 | video->getFrame(); 388 | if ((data = video->getData()) != nullptr) { 389 | save2file(data, video->getFrameSize(), fileName); 390 | } 391 | } 392 | video->stop(); 393 | } 394 | delete video; 395 | 396 | return 0; 397 | } 398 | -------------------------------------------------------------------------------- /video/regs-video.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* Copyright (C) 2021 Aspeed Technology Inc. */ 3 | 4 | typedef unsigned long u32; 5 | typedef unsigned short u16; 6 | typedef unsigned char u8; 7 | 8 | #define BYTE unsigned char 9 | #define INT int 10 | #define VOID void 11 | #define BOOLEAN unsigned short 12 | 13 | #ifndef Windows 14 | #define ULONG unsigned long 15 | #define USHORT unsigned short 16 | #define UCHAR unsigned char 17 | #endif 18 | 19 | 20 | #ifndef _STRUCTURE_INFO 21 | #define _STRUCTURE_INFO 22 | 23 | typedef struct _VIDEO_MODE_INFO 24 | { 25 | USHORT X; 26 | USHORT Y; 27 | USHORT ColorDepth; 28 | USHORT RefreshRate; 29 | BYTE ModeIndex; 30 | } VIDEO_MODE_INFO, *PVIDEO_MODE_INFO; 31 | 32 | typedef struct _VQ_INFO { 33 | BYTE Y[16]; 34 | BYTE U[32]; 35 | BYTE V[32]; 36 | BYTE NumberOfY; 37 | BYTE NumberOfUV; 38 | BYTE NumberOfInner; 39 | BYTE NumberOfOuter; 40 | } VQ_INFO, *PVQ_INFO; 41 | 42 | typedef struct _HUFFMAN_TABLE { 43 | ULONG HuffmanCode[32]; 44 | } HUFFMAN_TABLE, *PHUFFMAN_TABLE; 45 | 46 | typedef struct _FRAME_HEADER { 47 | ULONG StartCode; //0 48 | ULONG FrameNumber; ///4 49 | USHORT HSize; //8 50 | USHORT VSize; 51 | ULONG Reserved[2]; //12 13 14 52 | BYTE DirectMode; //15 53 | BYTE CompressionMode; //15 54 | BYTE JPEGScaleFactor; //16 55 | BYTE Y_JPEGTableSelector; //18 [[[[ 56 | BYTE JPEGYUVTableMapping; 57 | BYTE SharpModeSelection; 58 | BYTE AdvanceTableSelector; 59 | BYTE AdvanceScaleFactor; 60 | ULONG NumberOfMB; 61 | BYTE VQ_YLevel; 62 | BYTE VQ_UVLevel; 63 | VQ_INFO VQVectors; 64 | BYTE RC4Enable; 65 | BYTE Mode420; 66 | BYTE Visual_Lossless; 67 | } FRAME_HEADER, *PFRAME_HEADER; 68 | 69 | typedef struct _INF_DATA { 70 | unsigned char AST2500; 71 | unsigned char Input_Signale; //0: internel vga, 1, ext digital, 2, ext analog 72 | unsigned char Trigger_Mode; //0: capture, 1, ext digital, 2, ext analog 73 | BYTE DownScalingEnable; 74 | BYTE DifferentialSetting; 75 | USHORT AnalogDifferentialThreshold; 76 | USHORT DigitalDifferentialThreshold; 77 | BYTE AutoMode; 78 | BYTE DirectMode; //0: force sync mode 1: auto direct mode 79 | USHORT DelayControl; 80 | BYTE VQMode; 81 | BYTE JPEG_FILE; 82 | } INF_DATA, *PINF_DATA; 83 | 84 | typedef struct _COMPRESS_DATA { 85 | ULONG SourceFrameSize; 86 | ULONG CompressSize; 87 | ULONG HDebug; 88 | ULONG VDebug; 89 | } COMPRESS_DATA, *PCOMPRESS_DATA; 90 | 91 | //VIDEO Engine Info 92 | typedef struct _VIDEO_ENGINE_INFO { 93 | INF_DATA INFData; 94 | VIDEO_MODE_INFO SourceModeInfo; 95 | VIDEO_MODE_INFO DestinationModeInfo; 96 | VQ_INFO VQInfo; 97 | FRAME_HEADER FrameHeader; 98 | COMPRESS_DATA CompressData; 99 | BYTE ChipVersion; 100 | BYTE NoSignal; 101 | } VIDEO_ENGINE_INFO, *PVIDEO_ENGINE_INFO; 102 | 103 | typedef struct { 104 | USHORT HorizontalTotal; 105 | USHORT VerticalTotal; 106 | USHORT HorizontalActive; 107 | USHORT VerticalActive; 108 | BYTE RefreshRate; 109 | double HorizontalFrequency; 110 | USHORT HSyncTime; 111 | USHORT HBackPorch; 112 | USHORT VSyncTime; 113 | USHORT VBackPorch; 114 | USHORT HLeftBorder; 115 | USHORT HRightBorder; 116 | USHORT VBottomBorder; 117 | USHORT VTopBorder; 118 | } VESA_MODE; 119 | 120 | typedef struct { 121 | USHORT HorizontalActive; 122 | USHORT VerticalActive; 123 | USHORT RefreshRate; 124 | BYTE ADCIndex1; 125 | BYTE ADCIndex2; 126 | BYTE ADCIndex3; 127 | BYTE ADCIndex5; 128 | BYTE ADCIndex6; 129 | BYTE ADCIndex7; 130 | BYTE ADCIndex8; 131 | BYTE ADCIndex9; 132 | BYTE ADCIndexA; 133 | BYTE ADCIndexF; 134 | BYTE ADCIndex15; 135 | int HorizontalShift; 136 | int VerticalShift; 137 | } ADC_MODE; 138 | 139 | typedef struct { 140 | USHORT HorizontalActive; 141 | USHORT VerticalActive; 142 | USHORT RefreshRateIndex; 143 | double PixelClock; 144 | } INTERNAL_MODE; 145 | 146 | typedef struct _TRANSFER_HEADER { 147 | ULONG Data_Length; 148 | ULONG Blocks_Changed; 149 | USHORT User_Width; 150 | USHORT User_Height; 151 | BYTE Frist_frame; // 1: first frame 152 | BYTE Compress_type; //0:aspeed mode, 1:jpeg mode 153 | BYTE Trigger_mode; //0:capture, 1: compression, 2: buffer 154 | BYTE Data_format; //0:DCT, 1:DCTwVQ2 color, 2:DCTwVQ4 color 155 | BYTE RC4_Enable; 156 | BYTE RC4_Reset; //no use 157 | BYTE Y_Table; 158 | BYTE UV_Table; 159 | BYTE Mode_420; 160 | BYTE Direct_Mode; 161 | BYTE VQ_Mode; 162 | BYTE Disable_VGA; 163 | BYTE Differential_Enable; 164 | BYTE Auto_Mode; 165 | BYTE VGA_Status; 166 | BYTE RC4State; 167 | BYTE Advance_Table; 168 | } TRANSFER_HEADER, *PTRANSFER_HEADER; 169 | 170 | 171 | 172 | // RC4 structure 173 | struct rc4_state 174 | { 175 | int x; 176 | int y; 177 | int m[256]; 178 | }; 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /video/video.cc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | // Copyright (C) 2021 Aspeed Technology Inc. 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "video.h" 11 | 12 | //#define VIDEO_DEBUG 13 | 14 | int video_fd; 15 | void *video_stream_addr; 16 | 17 | int ast_video_open(void) 18 | { 19 | video_fd = open("/dev/ast-video", O_RDWR); 20 | if(video_fd == -1) { 21 | perror("Can't open /dev/ast-video, please install driver!! \n"); 22 | return -1; 23 | } 24 | return 0; 25 | } 26 | 27 | void ast_video_close(void) 28 | { 29 | close(video_fd); 30 | } 31 | 32 | void ast_video_reset(void) 33 | { 34 | if (ioctl(video_fd, AST_VIDEO_RESET, NULL) < 0) { 35 | printf("AST_VIDEO_RESET fail\n"); 36 | } 37 | } 38 | 39 | void ast_video_get_vga_signal(unsigned char *signal) 40 | { 41 | if (ioctl(video_fd, AST_VIDEO_IOC_GET_VGA_SIGNAL, signal) < 0) { 42 | printf("AST_VIDEO_IOC_GET_VGA_SIGNAL fail\n"); 43 | } 44 | } 45 | 46 | void *ast_video_mmap_stream_addr(void) 47 | { 48 | unsigned long video_mem_size; 49 | if (ioctl(video_fd, AST_VIDEO_GET_MEM_SIZE_IOCRX, &video_mem_size) < 0) { 50 | printf("AST_VIDEO_GET_MEM_SIZE_IOCRX fail\n"); 51 | return NULL; 52 | } else { 53 | #ifdef VIDEO_DEBUG 54 | printf("video memory size = %ldMB \n", video_mem_size/(1024 * 1024)); 55 | #endif 56 | video_stream_addr = mmap(0, video_mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, video_fd, 0); 57 | return video_stream_addr; 58 | } 59 | } 60 | 61 | void *ast_video_mmap_jpeg_addr(void) 62 | { 63 | unsigned long video_jpeg_offset; 64 | void *video_jpeg_addr; 65 | 66 | if (ioctl(video_fd, AST_VIDEO_GET_JPEG_OFFSET_IOCRX, &video_jpeg_offset) < 0) { 67 | printf("AST_VIDEO_GET_JPEG_OFFSET_IOCRX fail\n"); 68 | return NULL; 69 | } else { 70 | #ifdef VIDEO_DEBUG 71 | printf("video jpeg offset from %ldMB \n", video_jpeg_offset/(1024 * 1024)); 72 | #endif 73 | video_jpeg_addr = (char *)video_stream_addr + video_jpeg_offset; 74 | return video_jpeg_addr; 75 | } 76 | } 77 | 78 | void ast_video_eng_config(struct ast_video_config* video_config) 79 | { 80 | if (ioctl(video_fd, AST_VIDEO_ENG_CONFIG, video_config) < 0) { 81 | printf("AST_VIDEO_ENG_CONFIG fail\n"); 82 | } 83 | } 84 | 85 | void ast_video_vga_mode_detection(struct ast_mode_detection* mode_detection) 86 | { 87 | if (ioctl(video_fd, AST_VIDEO_VGA_MODE_DETECTION, mode_detection) < 0) { 88 | printf("AST_VIDEO_VGA_MODE_DETECTION fail\n"); 89 | } 90 | } 91 | 92 | void ast_video_set_scaling(struct ast_scaling* set_scaling) 93 | { 94 | if (ioctl(video_fd, AST_VIDEO_SET_SCALING, set_scaling) < 0) { 95 | printf("AST_VIDEO_SET_SCALING fail\n"); 96 | } 97 | } 98 | 99 | void ast_video_auto_mode_trigger(struct ast_auto_mode* auto_mode) 100 | { 101 | if (ioctl(video_fd, AST_VIDEO_AUTOMODE_TRIGGER, auto_mode) < 0) { 102 | printf("AST_VIDEO_AUTOMODE_TRIGGER fail\n"); 103 | } 104 | } 105 | 106 | void ast_video_capture_mode_trigger(struct ast_capture_mode* capture_mode) 107 | { 108 | if (ioctl(video_fd, AST_VIDEO_CAPTURE_TRIGGER, capture_mode) < 0) { 109 | printf("AST_VIDEO_CAPTURE_TRIGGER fail\n"); 110 | } 111 | } 112 | 113 | void ast_video_compression_mode_trigger(struct ast_compression_mode* compression_mode) 114 | { 115 | if (ioctl(video_fd, AST_VIDEO_COMPRESSION_TRIGGER, compression_mode) < 0) { 116 | printf("AST_VIDEO_COMPRESSION_TRIGGER fail\n"); 117 | } 118 | } 119 | 120 | void ast_video_set_vga_display(int *vga_enable) 121 | { 122 | if (ioctl(video_fd, AST_VIDEO_SET_VGA_DISPLAY, vga_enable) < 0) { 123 | printf("AST_VIDEO_SET_VGA_DISPLAY fail\n"); 124 | } 125 | } 126 | 127 | void ast_video_set_encryption(int enable) 128 | { 129 | if (ioctl(video_fd, AST_VIDEO_SET_ENCRYPTION, enable) < 0) { 130 | printf("AST_VIDEO_SET_ENCRYPTION fail\n"); 131 | } 132 | } 133 | 134 | void ast_video_set_encryption_key(unsigned char *key) 135 | { 136 | if (ioctl(video_fd, AST_VIDEO_SET_ENCRYPTION_KEY, key) < 0) { 137 | printf("AST_VIDEO_SET_ENCRYPTION_KEY fail\n"); 138 | } 139 | } 140 | 141 | void ast_video_set_crt_compression(struct fb_var_screeninfo *vinfo) 142 | { 143 | if (ioctl(video_fd, AST_VIDEO_SET_CRT_COMPRESSION, vinfo) < 0) { 144 | printf("AST_VIDEO_SET_CRT_COMPRESSION fail\n"); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /video/video.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* Copyright (C) 2021 Aspeed Technology Inc. */ 3 | 4 | #include 5 | 6 | /*************************************************************************************/ 7 | //VR08[2] 8 | typedef enum ast_video_source { 9 | VIDEO_SOURCE_INT_VGA = 0, 10 | VIDEO_SOURCE_INT_CRT, 11 | VIDEO_SOURCE_EXT_ADC, 12 | VIDEO_SOURCE_EXT_DIGITAL, 13 | } video_source; 14 | /*************************************************************************************/ 15 | //video engine initial 16 | struct video_eng_config { 17 | video_source input_source; 18 | unsigned char DifferentialSetting; 19 | unsigned char Auto_Mode; //force 1:auto, 0:capture and compress 20 | unsigned char Mode_420; 21 | unsigned char Direct_Mode; //no use : auto switch by driver detection --> TODO Sync_Mode 0: Auto direct 1:Force sync 22 | //TODO ~~ GRAY mode 23 | //encryption 24 | unsigned char RC4_Enable; 25 | unsigned char encrypt_key[256]; 26 | 27 | unsigned char Y_Table; 28 | 29 | //Visual_Lossless enable 30 | unsigned char Visual_Lossless; 31 | unsigned char Advance_Table; 32 | 33 | //scaling on/off 34 | unsigned char scaling; 35 | unsigned short User_Width; 36 | unsigned short User_Height; 37 | 38 | //JPEG config 39 | unsigned char Jpeg_en; 40 | unsigned char Jpeg_Mode_420; 41 | 42 | unsigned char Jpeg_Y_Table; 43 | 44 | //Visual_Lossless enable 45 | unsigned char Jpeg_Visual_Lossless; 46 | unsigned char Jpeg_Advance_Table; 47 | 48 | //scaling on/off 49 | unsigned char Jpeg_scaling; 50 | unsigned short Jpeg_User_Width; 51 | unsigned short Jpeg_User_Height; 52 | }; 53 | 54 | //video [stream/frame mode info] 55 | struct ast_video_info { 56 | unsigned char full_frame; 57 | unsigned long Data_Length; 58 | unsigned long Blocks_Changed; 59 | }; 60 | 61 | struct ast_video_config 62 | { 63 | unsigned char engine; //0: engine 0, engine 1 64 | unsigned char compression_mode; //0:DCT, 1:DCT_VQ mix VQ-2 color, 2:DCT_VQ mix VQ-4 color 9: 65 | unsigned char compression_format; //0:ASPEED 1:JPEG 66 | unsigned char capture_format; //0:CCIR601-2 YUV, 1:JPEG YUV, 2:RGB for ASPEED mode only, 3:Gray 67 | unsigned char rc4_enable; //0:disable 1:enable 68 | unsigned char EncodeKeys[256]; 69 | 70 | unsigned char YUV420_mode; //0:YUV444, 1:YUV420 71 | unsigned char Visual_Lossless; 72 | unsigned char Y_JPEGTableSelector; 73 | unsigned char AdvanceTableSelector; 74 | unsigned char AutoMode; 75 | }; 76 | 77 | struct ast_auto_mode 78 | { 79 | unsigned char engine_idx; //set 0: engine 0, engine 1 80 | unsigned char differential; //set 0: full, 1:diff frame 81 | unsigned char mode_change; //get 0: no, 1:change 82 | unsigned long total_size; //get 83 | unsigned long block_count; //get 84 | }; 85 | 86 | struct ast_scaling 87 | { 88 | unsigned char engine; //0: engine 0, engine 1 89 | unsigned char enable; 90 | unsigned short x; 91 | unsigned short y; 92 | }; 93 | 94 | struct ast_capture_mode { 95 | unsigned char engine_idx; //set 0: engine 0, engine 1 96 | unsigned char differential; //set 0: full, 1:diff frame 97 | unsigned char mode_change; //get 0: no, 1:change 98 | }; 99 | 100 | struct ast_compression_mode { 101 | unsigned char engine_idx; //set 0: engine 0, engine 1 102 | unsigned char mode_change; //get 0: no, 1:change 103 | unsigned long total_size; //get 104 | unsigned long block_count; //get 105 | }; 106 | 107 | struct fbinfo 108 | { 109 | unsigned short x; 110 | unsigned short y; 111 | unsigned char color_mode; //0:NON, 1:EGA, 2:VGA, 3:15bpp, 4:16bpp, 5:32bpp 112 | unsigned long PixelClock; 113 | }; 114 | 115 | struct ast_mode_detection 116 | { 117 | unsigned char result; //0: pass, 1: fail 118 | unsigned short src_x; 119 | unsigned short src_y; 120 | }; 121 | 122 | /*************************************************************************************/ 123 | #define VIDEOIOC_BASE 'V' 124 | 125 | #define AST_VIDEO_RESET _IO(VIDEOIOC_BASE, 0x0) 126 | #define AST_VIDEO_IOC_GET_VGA_SIGNAL _IOR(VIDEOIOC_BASE, 0x1, unsigned char) 127 | #define AST_VIDEO_GET_MEM_SIZE_IOCRX _IOR(VIDEOIOC_BASE, 0x2, unsigned long) 128 | #define AST_VIDEO_GET_JPEG_OFFSET_IOCRX _IOR(VIDEOIOC_BASE, 0x3, unsigned long) 129 | #define AST_VIDEO_VGA_MODE_DETECTION _IOWR(VIDEOIOC_BASE, 0x4, struct ast_mode_detection*) 130 | 131 | #define AST_VIDEO_ENG_CONFIG _IOW(VIDEOIOC_BASE, 0x5, struct ast_video_config*) 132 | #define AST_VIDEO_SET_SCALING _IOW(VIDEOIOC_BASE, 0x6, struct ast_scaling*) 133 | 134 | #define AST_VIDEO_AUTOMODE_TRIGGER _IOWR(VIDEOIOC_BASE, 0x7, struct ast_auto_mode*) 135 | #define AST_VIDEO_CAPTURE_TRIGGER _IOWR(VIDEOIOC_BASE, 0x8, struct ast_capture_mode*) 136 | #define AST_VIDEO_COMPRESSION_TRIGGER _IOWR(VIDEOIOC_BASE, 0x9, struct ast_compression_mode*) 137 | 138 | #define AST_VIDEO_SET_VGA_DISPLAY _IOW(VIDEOIOC_BASE, 0xa, int) 139 | #define AST_VIDEO_SET_ENCRYPTION _IOW(VIDEOIOC_BASE, 0xb, int) 140 | #define AST_VIDEO_SET_ENCRYPTION_KEY _IOW(VIDEOIOC_BASE, 0xc, unsigned char*) 141 | #define AST_VIDEO_SET_CRT_COMPRESSION _IOW(VIDEOIOC_BASE, 0xd, struct fb_var_screeninfo*) 142 | /*************************************************************************************/ 143 | int ast_video_open(void); 144 | void ast_video_close(void); 145 | void ast_video_reset(void); 146 | void ast_video_get_vga_signal(unsigned char *signal); 147 | void *ast_video_mmap_stream_addr(void); 148 | void *ast_video_mmap_jpeg_addr(void); 149 | void ast_video_vga_mode_detection(struct ast_mode_detection* mode_detection); 150 | void ast_video_set_scaling(struct ast_scaling* set_scaling); 151 | void ast_video_eng_config(struct ast_video_config* video_config); 152 | void ast_video_auto_mode_trigger(struct ast_auto_mode* auto_mode); 153 | void ast_video_capture_mode_trigger(struct ast_capture_mode* capture_mode); 154 | void ast_video_compression_mode_trigger(struct ast_compression_mode* compression_mode); 155 | void ast_video_set_vga_display(int *vga_enable); 156 | int ast_video_compression_trigger(struct ast_video_info *video_info); 157 | void ast_video_set_encryption(int enable); 158 | void ast_video_set_encryption_key(unsigned char *key); 159 | void ast_video_set_crt_compression( struct fb_var_screeninfo *vinfo); 160 | -------------------------------------------------------------------------------- /video/video.inf: -------------------------------------------------------------------------------- 1 | INPUT_SOURCE= 0 2 | COMPRESS_MODE= 0 3 | Y_JPEG_TABLESELECTION= 4 4 | UV_JPEG_TABLESELECTION= 20 5 | JPEG_YUVTABLE_MAPPING= 0 6 | JPEG_SCALE_FACTOR= 16 7 | SHARP_MODE_SELECTION= 0 8 | JPEG_VISUAL_LOSSLESS= 0 9 | JPEG_ADVANCE_TABLESELECTION= 7 10 | JPEG_ADVANCE_SCALE_FACTOR= 16 11 | DIFFERENTIAL_SETTING= 1 12 | DOWN_SCALING_ENABLE= 0 13 | DESTINATION_X= 640 14 | DESTINATION_Y= 480 15 | RC4_ENABLE= 0 16 | RC4_KEYS= fedcba9876543210 17 | ANALOG_DIFFERENTIAL_THRESHOLD= 8 18 | DIGITAL_DIFFERENTIAL_THRESHOLD= 0 19 | EXTERNAL_SIGNAL= 0 20 | AUTO_MODE= 1 21 | DIRECT_MODE= 0 22 | DELAY_CONTROL= 0 23 | MODE_420= 0 24 | VQ_MODE= 0 25 | JPEG_FILE= 0 26 | --------------------------------------------------------------------------------