Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | // SPDX-License-Identifier: GPL-2.0 #include <linux/export.h> #include <linux/ioport.h> #include <linux/screen_info.h> #include <linux/string.h> static void resource_init_named(struct resource *r, resource_size_t start, resource_size_t size, const char *name, unsigned int flags) { memset(r, 0, sizeof(*r)); r->start = start; r->end = start + size - 1; r->name = name; r->flags = flags; } static void resource_init_io_named(struct resource *r, resource_size_t start, resource_size_t size, const char *name) { resource_init_named(r, start, size, name, IORESOURCE_IO); } static void resource_init_mem_named(struct resource *r, resource_size_t start, resource_size_t size, const char *name) { resource_init_named(r, start, size, name, IORESOURCE_MEM); } static inline bool __screen_info_has_ega_gfx(unsigned int mode) { switch (mode) { case 0x0d: /* 320x200-4 */ case 0x0e: /* 640x200-4 */ case 0x0f: /* 640x350-1 */ case 0x10: /* 640x350-4 */ return true; default: return false; } } static inline bool __screen_info_has_vga_gfx(unsigned int mode) { switch (mode) { case 0x10: /* 640x480-1 */ case 0x12: /* 640x480-4 */ case 0x13: /* 320-200-8 */ case 0x6a: /* 800x600-4 (VESA) */ return true; default: return __screen_info_has_ega_gfx(mode); } } /** * screen_info_resources() - Get resources from screen_info structure * @si: the screen_info * @r: pointer to an array of resource structures * @num: number of elements in @r: * * Returns: * The number of resources stored in @r on success, or a negative errno code otherwise. * * A call to screen_info_resources() returns the resources consumed by the * screen_info's device or framebuffer. The result is stored in the caller-supplied * array @r with up to @num elements. The function returns the number of * initialized elements. */ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num) { struct resource *pos = r; unsigned int type = screen_info_video_type(si); u64 base, size; switch (type) { case VIDEO_TYPE_MDA: if (num > 0) resource_init_io_named(pos++, 0x3b0, 12, "mda"); if (num > 1) resource_init_io_named(pos++, 0x3bf, 0x01, "mda"); if (num > 2) resource_init_mem_named(pos++, 0xb0000, 0x2000, "mda"); break; case VIDEO_TYPE_CGA: if (num > 0) resource_init_io_named(pos++, 0x3d4, 0x02, "cga"); if (num > 1) resource_init_mem_named(pos++, 0xb8000, 0x2000, "cga"); break; case VIDEO_TYPE_EGAM: if (num > 0) resource_init_io_named(pos++, 0x3bf, 0x10, "ega"); if (num > 1) resource_init_mem_named(pos++, 0xb0000, 0x8000, "ega"); break; case VIDEO_TYPE_EGAC: if (num > 0) resource_init_io_named(pos++, 0x3c0, 0x20, "ega"); if (num > 1) { if (__screen_info_has_ega_gfx(si->orig_video_mode)) resource_init_mem_named(pos++, 0xa0000, 0x10000, "ega"); else resource_init_mem_named(pos++, 0xb8000, 0x8000, "ega"); } break; case VIDEO_TYPE_VGAC: if (num > 0) resource_init_io_named(pos++, 0x3c0, 0x20, "vga+"); if (num > 1) { if (__screen_info_has_vga_gfx(si->orig_video_mode)) resource_init_mem_named(pos++, 0xa0000, 0x10000, "vga+"); else resource_init_mem_named(pos++, 0xb8000, 0x8000, "vga+"); } break; case VIDEO_TYPE_VLFB: case VIDEO_TYPE_EFI: base = __screen_info_lfb_base(si); if (!base) break; size = __screen_info_lfb_size(si, type); if (!size) break; if (num > 0) resource_init_mem_named(pos++, base, size, "lfb"); break; case VIDEO_TYPE_PICA_S3: case VIDEO_TYPE_MIPS_G364: case VIDEO_TYPE_SGI: case VIDEO_TYPE_TGAC: case VIDEO_TYPE_SUN: case VIDEO_TYPE_SUNPCI: case VIDEO_TYPE_PMAC: default: /* not supported */ return -EINVAL; } return pos - r; } EXPORT_SYMBOL(screen_info_resources); |