26 #include "switchtec/portable.h" 28 #include "switchtec/utils.h" 29 #include "../switchtec_priv.h" 33 #include "windows/switchtec_public.h" 41 struct switchtec_windows {
42 struct switchtec_dev dev;
46 #define to_switchtec_windows(d) \ 47 ((struct switchtec_windows *) \ 48 ((char *)d - offsetof(struct switchtec_windows, dev))) 50 static int earlier_error = 0;
52 const char *platform_strerror(
void)
54 static char errmsg[500] =
"";
55 int err = GetLastError();
57 if (!err && earlier_error)
60 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
61 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
62 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
63 errmsg,
sizeof (errmsg), NULL);
66 sprintf(errmsg,
"Error %d", err);
70 static void platform_perror(
const char *msg)
72 fprintf(stderr,
"%s: %s\n", msg, platform_strerror());
75 static int count_devices(
void)
79 SP_DEVICE_INTERFACE_DATA deviface;
81 devinfo = SetupDiGetClassDevs(&SWITCHTEC_INTERFACE_GUID,
82 NULL, NULL, DIGCF_DEVICEINTERFACE |
85 deviface.cbSize =
sizeof(SP_DEVICE_INTERFACE_DATA);
87 while (SetupDiEnumDeviceInterfaces(devinfo, NULL,
88 &SWITCHTEC_INTERFACE_GUID,
94 static BOOL get_path(HDEVINFO devinfo, SP_DEVICE_INTERFACE_DATA *deviface,
95 SP_DEVINFO_DATA *devdata,
char *path,
size_t path_size)
98 SP_DEVICE_INTERFACE_DETAIL_DATA *devdetail;
102 devdata->cbSize =
sizeof(SP_DEVINFO_DATA);
104 SetupDiGetDeviceInterfaceDetail(devinfo, deviface, NULL, 0, &size,
107 devdetail = malloc(size);
109 perror(
"Enumeration");
113 devdetail->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
115 status = SetupDiGetDeviceInterfaceDetail(devinfo, deviface, devdetail,
116 size, NULL, devdata);
118 platform_perror(
"SetupDiGetDeviceInterfaceDetail");
122 strcpy_s(path, path_size, devdetail->DevicePath);
125 hash = strrchr(path,
'#');
134 static BOOL get_pci_address(HDEVINFO devinfo, SP_DEVINFO_DATA *devdata,
135 int *bus,
int *dev,
int *func)
141 status = SetupDiGetDeviceRegistryProperty(devinfo, devdata,
142 SPDRP_LOCATION_INFORMATION, NULL,
143 (BYTE *)loc,
sizeof(loc), NULL);
145 platform_perror(
"SetupDiGetDeviceRegistryProperty (LOC)");
149 ret = sscanf(loc,
"PCI bus %d, device %d, function %d", bus, dev, func);
151 fprintf(stderr,
"Error parsing PCI BUS: '%s'\n", loc);
158 static void get_pci_address_str(HDEVINFO devinfo, SP_DEVINFO_DATA *devdata,
159 char *res,
size_t res_size)
164 status = get_pci_address(devinfo, devdata, &bus, &dev, &func);
166 snprintf(res, res_size,
"??:??.?");
168 snprintf(res, res_size,
"%02x:%02x.%x", bus, dev, func);
171 static void get_description(HDEVINFO devinfo, SP_DEVINFO_DATA *devdata,
172 char *res,
size_t res_size)
174 SetupDiGetDeviceRegistryProperty(devinfo, devdata,
175 SPDRP_DEVICEDESC, NULL,(BYTE *)res, res_size, NULL);
182 WINSETUPAPI WINBOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO DeviceInfoSet,
183 PSP_DEVINFO_DATA DeviceInfoData,
const DEVPROPKEY *PropertyKey,
184 DEVPROPTYPE *PropertyType, PBYTE PropertyBuffer,
185 DWORD PropertyBufferSize, PDWORD RequiredSize,
188 static void get_property(HDEVINFO devinfo, SP_DEVINFO_DATA *devdata,
189 const DEVPROPKEY *propkey,
char *res,
size_t res_size)
194 SetupDiGetDevicePropertyW(devinfo, devdata, propkey, &ptype,
195 (PBYTE)buf,
sizeof(buf), NULL, 0);
196 wcstombs(res, buf, res_size);
199 static void get_fw_property(HDEVINFO devinfo, SP_DEVINFO_DATA *devdata,
200 char *res,
size_t res_size)
205 get_property(devinfo, devdata, &SWITCHTEC_PROP_FW_VERSION,
208 fw_ver = strtol(buf, NULL, 16);
211 snprintf(res, res_size,
"unknown");
213 version_to_string(fw_ver, res, res_size);
216 static void append_guid(
const char *path,
char *path_with_guid,
size_t bufsize,
219 snprintf(path_with_guid, bufsize,
220 "%s#{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
221 path, guid->Data1, guid->Data2, guid->Data3,
222 guid->Data4[0], guid->Data4[1], guid->Data4[2],
223 guid->Data4[3], guid->Data4[4], guid->Data4[5],
224 guid->Data4[6], guid->Data4[7]);
228 #define __force __attribute__((force)) 233 static BOOL map_gas(
struct switchtec_windows *wdev)
238 status = DeviceIoControl(wdev->hdl, IOCTL_SWITCHTEC_GAS_MAP, NULL, 0,
239 &map,
sizeof(map), NULL, NULL);
241 earlier_error = GetLastError();
245 wdev->dev.gas_map = (
gasptr_t __force)map.gas;
246 wdev->dev.gas_map_size = map.length;
250 static void unmap_gas(
struct switchtec_windows *wdev)
253 .gas = (
void * __force)wdev->dev.gas_map,
254 .length = wdev->dev.gas_map_size,
257 DeviceIoControl(wdev->hdl, IOCTL_SWITCHTEC_GAS_UNMAP, &map,
sizeof(map),
258 NULL, 0, NULL, NULL);
261 static void windows_close(
struct switchtec_dev *dev)
263 struct switchtec_windows *wdev = to_switchtec_windows(dev);
266 CloseHandle(wdev->hdl);
272 SP_DEVICE_INTERFACE_DATA deviface;
273 SP_DEVINFO_DATA devdata;
280 dl = *devlist = calloc(count_devices(),
287 devinfo = SetupDiGetClassDevs(&SWITCHTEC_INTERFACE_GUID,
288 NULL, NULL, DIGCF_DEVICEINTERFACE |
290 if (devinfo == INVALID_HANDLE_VALUE)
293 deviface.cbSize =
sizeof(SP_DEVICE_INTERFACE_DATA);
295 while (SetupDiEnumDeviceInterfaces(devinfo, NULL,
296 &SWITCHTEC_INTERFACE_GUID,
299 snprintf(dl[cnt].
name,
sizeof(dl[cnt].name),
300 "switchtec%ld", idx++);
302 status = get_path(devinfo, &deviface, &devdata,
303 dl[cnt].path,
sizeof(dl[cnt].path));
307 get_pci_address_str(devinfo, &devdata, dl[cnt].
pci_dev,
308 sizeof(dl[cnt].pci_dev));
309 get_description(devinfo, &devdata, dl[cnt].
desc,
310 sizeof(dl[cnt].desc));
312 get_property(devinfo, &devdata, &SWITCHTEC_PROP_PRODUCT_ID,
313 dl[cnt].
product_id,
sizeof(dl[cnt].product_id));
314 get_property(devinfo, &devdata, &SWITCHTEC_PROP_PRODUCT_REV,
316 get_fw_property(devinfo, &devdata, dl[cnt].
fw_version,
317 sizeof(dl[cnt].fw_version));
321 SetupDiDestroyDeviceInfoList(devinfo);
326 static int windows_cmd(
struct switchtec_dev *dev, uint32_t cmd,
327 const void *payload,
size_t payload_len,
void *resp,
330 struct switchtec_windows *wdev = to_switchtec_windows(dev);
334 struct switchtec_mrpc_cmd *mcmd;
335 struct switchtec_mrpc_result *mres;
336 size_t mcmd_len, mres_len;
338 mcmd_len = offsetof(
struct switchtec_mrpc_cmd, data) + payload_len;
339 mres_len = offsetof(
struct switchtec_mrpc_result, data) + resp_len;
341 mcmd = calloc(1, mcmd_len);
345 mres = calloc(1, mres_len);
352 memcpy(mcmd->data, payload, payload_len);
354 status = DeviceIoControl(wdev->hdl, IOCTL_SWITCHTEC_MRPC,
355 mcmd, (DWORD)mcmd_len,
356 mres, (DWORD)mres_len,
364 memcpy(resp, mres->data, resp_len);
374 static int windows_event_wait(
struct switchtec_dev *dev,
int timeout_ms)
376 struct switchtec_windows *wdev = to_switchtec_windows(dev);
377 OVERLAPPED overlap = {
378 .hEvent = CreateEvent(NULL, TRUE, FALSE, NULL),
389 DeviceIoControl(wdev->hdl, IOCTL_SWITCHTEC_WAIT_FOR_EVENT, NULL, 0,
390 NULL, 0, NULL, &overlap);
391 if (GetLastError() != ERROR_IO_PENDING)
394 ret = WaitForSingleObject(overlap.hEvent, timeout_ms);
395 if (ret == WAIT_TIMEOUT) {
396 CancelIoEx(wdev->hdl, &overlap);
402 error = GetOverlappedResult(wdev->hdl, &overlap, &transferred, FALSE);
409 static gasptr_t windows_gas_map(
struct switchtec_dev *dev,
int writeable,
415 *map_size = dev->gas_map_size;
417 ret = gasop_access_check(dev);
420 return SWITCHTEC_MAP_FAILED;
425 static const struct switchtec_ops windows_ops = {
426 .close = windows_close,
428 .gas_map = windows_gas_map,
429 .event_wait = windows_event_wait,
431 .get_device_id = gasop_get_device_id,
432 .get_fw_version = gasop_get_fw_version,
433 .pff_to_port = gasop_pff_to_port,
434 .port_to_pff = gasop_port_to_pff,
435 .flash_part = gasop_flash_part,
436 .event_summary = gasop_event_summary,
437 .event_ctl = gasop_event_ctl,
439 .gas_read8 = mmap_gas_read8,
440 .gas_read16 = mmap_gas_read16,
441 .gas_read32 = mmap_gas_read32,
442 .gas_read64 = mmap_gas_read64,
443 .gas_write8 = mmap_gas_write8,
444 .gas_write16 = mmap_gas_write16,
445 .gas_write32 = mmap_gas_write32,
446 .gas_write32_no_retry = mmap_gas_write32,
447 .gas_write64 = mmap_gas_write64,
448 .memcpy_to_gas = mmap_memcpy_to_gas,
449 .memcpy_from_gas = mmap_memcpy_from_gas,
450 .write_from_gas = mmap_write_from_gas,
455 struct switchtec_windows *wdev;
456 char path_with_guid[MAX_PATH];
459 if (sscanf(path,
"/dev/switchtec%d", &idx) == 1)
462 wdev = malloc(
sizeof(*wdev));
466 append_guid(path, path_with_guid,
sizeof(path_with_guid),
467 &SWITCHTEC_INTERFACE_GUID);
469 wdev->hdl = CreateFile(path_with_guid, GENERIC_READ | GENERIC_WRITE,
470 FILE_SHARE_READ | FILE_SHARE_WRITE,
471 NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
473 if (wdev->hdl == INVALID_HANDLE_VALUE)
479 wdev->dev.ops = &windows_ops;
481 gasop_set_partition_info(&wdev->dev);
486 CloseHandle(wdev->hdl);
495 SP_DEVICE_INTERFACE_DATA deviface;
496 SP_DEVINFO_DATA devdata;
498 struct switchtec_dev *dev = NULL;
501 devinfo = SetupDiGetClassDevs(&SWITCHTEC_INTERFACE_GUID,
502 NULL, NULL, DIGCF_DEVICEINTERFACE |
504 if (devinfo == INVALID_HANDLE_VALUE)
507 deviface.cbSize =
sizeof(SP_DEVICE_INTERFACE_DATA);
509 status = SetupDiEnumDeviceInterfaces(devinfo, NULL,
510 &SWITCHTEC_INTERFACE_GUID,
517 status = get_path(devinfo, &deviface, &devdata,
525 SetupDiDestroyDeviceInfoList(devinfo);
530 int device,
int func)
533 SP_DEVICE_INTERFACE_DATA deviface;
534 SP_DEVINFO_DATA devdata;
536 struct switchtec_dev *dev = NULL;
538 int dbus, ddevice, dfunc;
541 devinfo = SetupDiGetClassDevs(&SWITCHTEC_INTERFACE_GUID,
542 NULL, NULL, DIGCF_DEVICEINTERFACE |
544 if (devinfo == INVALID_HANDLE_VALUE)
547 deviface.cbSize =
sizeof(SP_DEVICE_INTERFACE_DATA);
549 while (SetupDiEnumDeviceInterfaces(devinfo, NULL,
550 &SWITCHTEC_INTERFACE_GUID,
553 status = get_path(devinfo, &deviface, &devdata,
558 get_pci_address(devinfo, &devdata, &dbus, &ddevice, &dfunc);
559 if (dbus == bus && ddevice == device && dfunc == func) {
568 SetupDiDestroyDeviceInfoList(devinfo);
578 struct switchtec_dev *switchtec_open_i2c_by_adapter(
int adapter,
int i2c_addr)
char product_rev[8]
Product revision.
Gas Operations for platforms that the gas is mapped into the address space.
gasptr_t switchtec_gas_map(struct switchtec_dev *dev, int writeable, size_t *map_size)
Map the GAS and return a pointer to access the gas.
__gas struct switchtec_gas * gasptr_t
Shortform for a pointer to the GAS register space.
char product_id[32]
Product ID.
int switchtec_list(struct switchtec_device_info **devlist)
List all the switchtec devices in the system.
char desc[256]
Device description, if available.
char pci_dev[256]
PCI BDF string.
struct switchtec_dev * switchtec_open_uart(int fd)
Open a switchtec device behind a uart device.
struct switchtec_dev * switchtec_open_by_path(const char *path)
Open a switchtec device by path.
char fw_version[32]
Firmware version.
char name[256]
Device name, eg. switchtec0.
Represents a Switchtec device in the switchtec_list() function.
struct switchtec_dev * switchtec_open_i2c(const char *path, int i2c_addr)
Open a switchtec device behind an I2C device.
struct switchtec_dev * switchtec_open_by_index(int index)
Open a switchtec device by index.
struct switchtec_dev * switchtec_open_by_pci_addr(int domain, int bus, int device, int func)
Open a switchtec device by PCI address (BDF)