Skip to content

Commit bdef66e

Browse files
committed
重写 sysfs 架构,补充部分功能.
1 parent e94281e commit bdef66e

File tree

13 files changed

+1709
-348
lines changed

13 files changed

+1709
-348
lines changed

src/driver/drm/drm.c

Lines changed: 265 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -447,38 +447,267 @@ static int drm_mode_resolve_obj_type(drm_device_t *dev, uint32_t obj_id, uint32_
447447
return 0;
448448
}
449449

450-
static void drm_sysfs_write_file(vfs_node_t parent, const char *name, const char *content) {
451-
vfs_node_t node;
452-
sysfs_handle_t *handle;
453-
size_t len;
450+
typedef enum drm_sysfs_attr {
451+
DRM_SYSFS_ATTR_VERSION,
452+
DRM_SYSFS_ATTR_DEV,
453+
DRM_SYSFS_ATTR_MODES,
454+
DRM_SYSFS_ATTR_UEVENT,
455+
} drm_sysfs_attr_t;
456+
457+
typedef struct drm_sysfs_file {
458+
sysfs_handle_t handle;
459+
drm_device_t *dev;
460+
drm_sysfs_attr_t attr;
461+
} drm_sysfs_file_t;
462+
463+
static char *drm_sysfs_join_path(vfs_node_t parent, const char *name) {
464+
if (parent == NULL || name == NULL) {
465+
return NULL;
466+
}
467+
468+
char *base = vfs_get_fullpath(parent);
469+
if (base == NULL) {
470+
return NULL;
471+
}
472+
473+
size_t base_len = strlen(base);
474+
size_t name_len = strlen(name);
475+
size_t path_len = base_len + name_len + 2;
476+
char *path = malloc(path_len);
477+
if (path == NULL) {
478+
free(base);
479+
return NULL;
480+
}
481+
482+
if (strcmp(base, "/") == 0) {
483+
sprintf(path, "/%s", name);
484+
} else {
485+
sprintf(path, "%s/%s", base, name);
486+
}
487+
488+
free(base);
489+
return path;
490+
}
491+
492+
static vfs_node_t drm_sysfs_lookup_child(vfs_node_t parent, const char *name) {
493+
char *path = drm_sysfs_join_path(parent, name);
494+
if (path == NULL) {
495+
return NULL;
496+
}
497+
498+
vfs_node_t node = vfs_open(path);
499+
free(path);
500+
return node;
501+
}
454502

455-
if (!parent || !name || !content) {
503+
static void drm_sysfs_release_handle(vfs_node_t node) {
504+
if (node == NULL || node->handle == NULL) {
456505
return;
457506
}
458507

459-
node = sysfs_child_append(parent, name, false);
460-
if (!node) {
508+
sysfs_header_t *header = node->handle;
509+
if (header->type == SYSFS_NONE) {
510+
sysfs_handle_t *handle = node->handle;
511+
if (handle->data != NULL) {
512+
free(handle->data);
513+
}
514+
}
515+
516+
free(node->handle);
517+
node->handle = NULL;
518+
}
519+
520+
static size_t drm_sysfs_format_modes_text(
521+
drm_device_t *drm_dev, char *buffer, size_t buffer_size
522+
) {
523+
uint32_t width = 1024;
524+
uint32_t height = 768;
525+
uint32_t bpp = 32;
526+
527+
for (size_t i = 0; i < DRM_MAX_CONNECTORS_PER_DEVICE; i++) {
528+
drm_connector_t *connector = drm_dev->resource_mgr.connectors[i];
529+
if (connector == NULL || connector->modes == NULL || connector->count_modes == 0) {
530+
continue;
531+
}
532+
533+
width = connector->modes[0].hdisplay;
534+
height = connector->modes[0].vdisplay;
535+
goto out;
536+
}
537+
538+
if (drm_dev->op && drm_dev->op->get_display_info) {
539+
drm_dev->op->get_display_info(drm_dev, &width, &height, &bpp);
540+
}
541+
542+
out:
543+
snprintf(buffer, buffer_size, "%ux%u\n", width, height);
544+
return strlen(buffer);
545+
}
546+
547+
static size_t drm_sysfs_format_dev_text(drm_device_t *drm_dev, char *buffer, size_t buffer_size) {
548+
int major = (drm_dev->dev_nr >> 8) & 0xff;
549+
int minor = drm_dev->dev_nr & 0xff;
550+
551+
snprintf(buffer, buffer_size, "%d:%d\n", major, minor);
552+
return strlen(buffer);
553+
}
554+
555+
static size_t drm_sysfs_format_uevent_text(
556+
drm_device_t *drm_dev, char *buffer, size_t buffer_size
557+
) {
558+
int minor = drm_dev->dev_nr & 0xff;
559+
int major = (drm_dev->dev_nr >> 8) & 0xff;
560+
char dev_name[32];
561+
562+
snprintf(dev_name, sizeof(dev_name), "card%d", minor);
563+
snprintf(
564+
buffer,
565+
buffer_size,
566+
"MAJOR=%d\nMINOR=%d\nDEVNAME=dri/%s\nDEVTYPE=drm_minor\nSUBSYSTEM=drm\n",
567+
major,
568+
minor,
569+
dev_name
570+
);
571+
return strlen(buffer);
572+
}
573+
574+
static size_t drm_sysfs_format_attr(
575+
drm_sysfs_file_t *handle, char *buffer, size_t buffer_size
576+
) {
577+
if (handle == NULL || buffer == NULL || buffer_size == 0) {
578+
return 0;
579+
}
580+
581+
switch (handle->attr) {
582+
case DRM_SYSFS_ATTR_VERSION:
583+
snprintf(buffer, buffer_size, "drm 1.1.0 20060810\n");
584+
return strlen(buffer);
585+
case DRM_SYSFS_ATTR_DEV:
586+
return drm_sysfs_format_dev_text(handle->dev, buffer, buffer_size);
587+
case DRM_SYSFS_ATTR_MODES:
588+
return drm_sysfs_format_modes_text(handle->dev, buffer, buffer_size);
589+
case DRM_SYSFS_ATTR_UEVENT:
590+
return drm_sysfs_format_uevent_text(handle->dev, buffer, buffer_size);
591+
default:
592+
return 0;
593+
}
594+
}
595+
596+
static size_t drm_sysfs_attr_read(void *file, void *addr, size_t offset, size_t size) {
597+
drm_sysfs_file_t *handle = file;
598+
if (handle == NULL || handle->dev == NULL || addr == NULL) {
599+
return 0;
600+
}
601+
602+
char content[256];
603+
size_t len = drm_sysfs_format_attr(handle, content, sizeof(content));
604+
if (len == 0 || offset >= len) {
605+
return 0;
606+
}
607+
608+
size_t actual = len - offset;
609+
if (actual > size) {
610+
actual = size;
611+
}
612+
613+
memcpy(addr, content + offset, actual);
614+
return actual;
615+
}
616+
617+
static size_t drm_sysfs_attr_write(void *file, const void *addr, size_t offset, size_t size) {
618+
drm_sysfs_file_t *handle = file;
619+
UNUSED(addr, offset);
620+
621+
if (handle == NULL) {
622+
return 0;
623+
}
624+
625+
return handle->attr == DRM_SYSFS_ATTR_UEVENT ? size : 0;
626+
}
627+
628+
static void drm_sysfs_install_attr_file(
629+
vfs_node_t parent, const char *name, drm_device_t *drm_dev, drm_sysfs_attr_t attr
630+
) {
631+
vfs_node_t node = drm_sysfs_lookup_child(parent, name);
632+
if (node == NULL) {
633+
node = sysfs_child_append(parent, name, SYSFS_NONE);
634+
}
635+
if (node == NULL) {
461636
return;
462637
}
463638

464-
handle = node->handle;
465-
len = strlen(content);
466-
handle->data = strdup(content);
467-
handle->size = len;
468-
handle->capacity = len + 1;
469-
node->size = len;
639+
drm_sysfs_release_handle(node);
640+
641+
drm_sysfs_file_t *handle = calloc(1, sizeof(drm_sysfs_file_t));
642+
strncpy(handle->handle.name, name, sizeof(handle->handle.name) - 1);
643+
handle->handle.header.node = node;
644+
handle->handle.header.type = SYSFS_NONE;
645+
handle->handle.header.read = drm_sysfs_attr_read;
646+
handle->handle.header.write = drm_sysfs_attr_write;
647+
handle->dev = drm_dev;
648+
handle->attr = attr;
649+
650+
node->handle = handle;
651+
char content[256];
652+
node->size = drm_sysfs_format_attr(handle, content, sizeof(content));
653+
node->mode = attr == DRM_SYSFS_ATTR_UEVENT ? 0644 : 0444;
654+
}
655+
656+
static void drm_sysfs_ensure_symlink(vfs_node_t parent, const char *name, const char *target) {
657+
if (parent == NULL || name == NULL || target == NULL) {
658+
return;
659+
}
660+
661+
if (drm_sysfs_lookup_child(parent, name) != NULL) {
662+
return;
663+
}
664+
665+
sysfs_child_append_symlink(parent, name, target);
666+
}
667+
668+
static void drm_sysfs_ensure_symlink_node(vfs_node_t parent, const char *name, vfs_node_t target) {
669+
if (parent == NULL || name == NULL || target == NULL) {
670+
return;
671+
}
672+
673+
if (drm_sysfs_lookup_child(parent, name) != NULL) {
674+
return;
675+
}
676+
677+
sysfs_child_append_symlink_node(parent, name, target);
678+
}
679+
680+
static vfs_node_t drm_sysfs_get_device_root(drm_device_t *drm_dev, const char *dev_name) {
681+
if (drm_dev->pci_dev != NULL) {
682+
return sysfs_get_pci_device_node(
683+
drm_dev->pci_dev->segment,
684+
drm_dev->pci_dev->bus,
685+
drm_dev->pci_dev->slot,
686+
drm_dev->pci_dev->func
687+
);
688+
}
689+
690+
vfs_node_t system_root = sysfs_ensure_dir(sysfs_get_devices_root(), "system");
691+
if (system_root == NULL) {
692+
return NULL;
693+
}
694+
695+
vfs_node_t display_root = sysfs_ensure_dir(system_root, "display");
696+
if (display_root == NULL) {
697+
return NULL;
698+
}
699+
700+
char device_name[48];
701+
snprintf(device_name, sizeof(device_name), "%s-device", dev_name);
702+
return sysfs_ensure_dir(display_root, device_name);
470703
}
471704

472705
static void drm_sysfs_register_device(drm_device_t *drm_dev) {
473-
vfs_node_t dev_char_dir;
474-
vfs_node_t dev_root;
475706
vfs_node_t device_dir;
476707
vfs_node_t drm_dir;
477708
vfs_node_t card_dir;
478-
vfs_node_t class_dir;
479709
vfs_node_t class_drm_dir;
480710
char dev_name[32];
481-
char path[256];
482711
char content[128];
483712
int major;
484713
int minor;
@@ -487,88 +716,42 @@ static void drm_sysfs_register_device(drm_device_t *drm_dev) {
487716
return;
488717
}
489718

490-
dev_char_dir = vfs_open("/sys/dev/char");
491-
if (!dev_char_dir) {
492-
return;
493-
}
494-
vfs_close(dev_char_dir);
495-
496719
major = (drm_dev->dev_nr >> 8) & 0xff;
497720
minor = drm_dev->dev_nr & 0xff;
498-
sprintf(dev_name, "card%d", minor);
721+
snprintf(dev_name, sizeof(dev_name), "card%d", minor);
499722

500-
sprintf(content, "SUBSYSTEM=drm\n");
501-
dev_root = sysfs_regist_dev('c', major, minor, "", dev_name, content);
502-
if (!dev_root) {
503-
return;
504-
}
505-
506-
device_dir = sysfs_child_append(dev_root, "device", true);
723+
device_dir = drm_sysfs_get_device_root(drm_dev, dev_name);
507724
if (!device_dir) {
508725
return;
509726
}
510727

511-
drm_dir = sysfs_child_append(device_dir, "drm", true);
728+
drm_dir = sysfs_ensure_dir(device_dir, "drm");
512729
if (!drm_dir) {
513730
return;
514731
}
515732

516-
card_dir = sysfs_child_append(drm_dir, dev_name, true);
733+
card_dir = sysfs_ensure_dir(drm_dir, dev_name);
517734
if (!card_dir) {
518735
return;
519736
}
520737

521-
if (drm_dev->pci_dev) {
522-
sprintf(
523-
content,
524-
"PCI_SLOT_NAME=%04x:%02x:%02x.%u\n",
525-
drm_dev->pci_dev->segment,
526-
drm_dev->pci_dev->bus,
527-
drm_dev->pci_dev->slot,
528-
drm_dev->pci_dev->func
529-
);
530-
} else {
531-
sprintf(content, "PCI_SLOT_NAME=0000:00:00.0\n");
532-
}
533-
drm_sysfs_write_file(device_dir, "uevent", content);
534-
sprintf(content, "0x%04x\n", drm_dev->pci_dev ? drm_dev->pci_dev->vendor_id : 0);
535-
drm_sysfs_write_file(device_dir, "vendor", content);
536-
sprintf(content, "0x%04x\n", drm_dev->pci_dev ? drm_dev->pci_dev->device_id : 0);
537-
drm_sysfs_write_file(device_dir, "device", content);
538-
sprintf(
539-
content,
540-
"0x%04x\n",
541-
drm_dev->pci_dev ? drm_dev->pci_dev->subsystem_vendor_id : 0
542-
);
543-
drm_sysfs_write_file(device_dir, "subsystem_vendor", content);
544-
sprintf(
545-
content,
546-
"0x%04x\n",
547-
drm_dev->pci_dev ? drm_dev->pci_dev->subsystem_device_id : 0
548-
);
549-
drm_sysfs_write_file(device_dir, "subsystem_device", content);
550-
sprintf(content, "0x%02x\n", drm_dev->pci_dev ? drm_dev->pci_dev->revision_id : 0);
551-
drm_sysfs_write_file(device_dir, "revision", content);
552-
drm_sysfs_write_file(drm_dir, "version", "drm 1.1.0 20060810\n");
553-
554-
sprintf(content, "MAJOR=%d\nMINOR=%d\nDEVNAME=dri/%s\nSUBSYSTEM=drm\n", major, minor, dev_name);
555-
drm_sysfs_write_file(card_dir, "uevent", content);
738+
drm_sysfs_install_attr_file(drm_dir, "version", drm_dev, DRM_SYSFS_ATTR_VERSION);
739+
drm_sysfs_install_attr_file(card_dir, "dev", drm_dev, DRM_SYSFS_ATTR_DEV);
740+
drm_sysfs_install_attr_file(card_dir, "modes", drm_dev, DRM_SYSFS_ATTR_MODES);
741+
drm_sysfs_install_attr_file(card_dir, "uevent", drm_dev, DRM_SYSFS_ATTR_UEVENT);
742+
drm_sysfs_ensure_symlink(card_dir, "subsystem", "/sys/class/drm");
743+
drm_sysfs_ensure_symlink_node(card_dir, "device", device_dir);
556744

557-
sysfs_child_append_symlink(card_dir, "subsystem", "/sys/class/drm");
558-
sysfs_child_append_symlink(device_dir, "subsystem", "/sys/bus/pci");
745+
class_drm_dir = sysfs_ensure_dir(sysfs_get_class_root(), "drm");
746+
if (class_drm_dir) {
747+
drm_sysfs_ensure_symlink_node(class_drm_dir, dev_name, card_dir);
748+
}
559749

560-
class_dir = vfs_open("/sys/class");
561-
if (class_dir) {
562-
class_drm_dir = vfs_open("/sys/class/drm");
563-
if (!class_drm_dir) {
564-
class_drm_dir = sysfs_child_append(class_dir, "drm", true);
565-
}
566-
if (class_drm_dir) {
567-
sprintf(path, "/sys/dev/char/%d:%d/device/drm/%s", major, minor, dev_name);
568-
sysfs_child_append_symlink(class_drm_dir, dev_name, path);
569-
vfs_close(class_drm_dir);
570-
}
571-
vfs_close(class_dir);
750+
drm_sysfs_format_uevent_text(drm_dev, content, sizeof(content));
751+
char *card_path = vfs_get_fullpath(card_dir);
752+
if (card_path != NULL) {
753+
sysfs_regist_dev('c', major, minor, card_path, dev_name, content);
754+
free(card_path);
572755
}
573756
}
574757

0 commit comments

Comments
 (0)