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