1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * eisa_enumerator.c - provide support for EISA adapters in PA-RISC machines 4 * 5 * Copyright (c) 2002 Daniel Engstrom <5116@telia.com> 6 */ 7 8 #include <linux/ioport.h> 9 #include <linux/init.h> 10 #include <linux/kernel.h> 11 #include <linux/slab.h> 12 #include <asm/io.h> 13 #include <linux/uaccess.h> 14 #include <asm/byteorder.h> 15 16 #include <asm/eisa_bus.h> 17 #include <asm/eisa_eeprom.h> 18 19 20 /* 21 * Todo: 22 * 23 * PORT init with MASK attr and other size than byte 24 * MEMORY with other decode than 20 bit 25 * CRC stuff 26 * FREEFORM stuff 27 */ 28 29 #define EPI 0xc80 30 #define NUM_SLOT 16 31 #define SLOT2PORT(x) (x<<12) 32 33 34 /* macros to handle unaligned accesses and 35 * byte swapping. The data in the EEPROM is 36 * little-endian on the big-endian PAROSC */ 37 #define get_8(x) (*(u_int8_t*)(x)) 38 39 static inline u_int16_t get_16(const unsigned char *x) 40 { 41 return (x[1] << 8) | x[0]; 42 } 43 44 static inline u_int32_t get_32(const unsigned char *x) 45 { 46 return (x[3] << 24) | (x[2] << 16) | (x[1] << 8) | x[0]; 47 } 48 49 static inline u_int32_t get_24(const unsigned char *x) 50 { 51 return (x[2] << 24) | (x[1] << 16) | (x[0] << 8); 52 } 53 54 static void print_eisa_id(char *s, u_int32_t id) 55 { 56 char vendor[4]; 57 int rev; 58 int device; 59 60 rev = id & 0xff; 61 id >>= 8; 62 device = id & 0xff; 63 id >>= 8; 64 vendor[3] = '\0'; 65 vendor[2] = '@' + (id & 0x1f); 66 id >>= 5; 67 vendor[1] = '@' + (id & 0x1f); 68 id >>= 5; 69 vendor[0] = '@' + (id & 0x1f); 70 id >>= 5; 71 72 sprintf(s, "%s%02X%02X", vendor, device, rev); 73 } 74 75 static int configure_memory(const unsigned char *buf, 76 struct resource *mem_parent, 77 char *name) 78 { 79 int len; 80 u_int8_t c; 81 int i; 82 struct resource *res; 83 84 len=0; 85 86 for (i=0;i<HPEE_MEMORY_MAX_ENT;i++) { 87 c = get_8(buf+len); 88 89 if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) { 90 int result; 91 92 res->name = name; 93 res->start = mem_parent->start + get_24(buf+len+2); 94 res->end = res->start + get_16(buf+len+5)*1024; 95 res->flags = IORESOURCE_MEM; 96 printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); 97 result = request_resource(mem_parent, res); 98 if (result < 0) { 99 printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); 100 return result; 101 } 102 } 103 104 len+=7; 105 106 if (!(c & HPEE_MEMORY_MORE)) { 107 break; 108 } 109 } 110 111 return len; 112 } 113 114 115 static int configure_irq(const unsigned char *buf) 116 { 117 int len; 118 u_int8_t c; 119 int i; 120 121 len=0; 122 123 for (i=0;i<HPEE_IRQ_MAX_ENT;i++) { 124 c = get_8(buf+len); 125 126 printk("IRQ %d ", c & HPEE_IRQ_CHANNEL_MASK); 127 if (c & HPEE_IRQ_TRIG_LEVEL) { 128 eisa_make_irq_level(c & HPEE_IRQ_CHANNEL_MASK); 129 } else { 130 eisa_make_irq_edge(c & HPEE_IRQ_CHANNEL_MASK); 131 } 132 133 len+=2; 134 /* hpux seems to allow for 135 * two bytes of irq data but only defines one of 136 * them, I think */ 137 if (!(c & HPEE_IRQ_MORE)) { 138 break; 139 } 140 } 141 142 return len; 143 } 144 145 146 static int configure_dma(const unsigned char *buf) 147 { 148 int len; 149 u_int8_t c; 150 int i; 151 152 len=0; 153 154 for (i=0;i<HPEE_DMA_MAX_ENT;i++) { 155 c = get_8(buf+len); 156 printk("DMA %d ", c&HPEE_DMA_CHANNEL_MASK); 157 /* fixme: maybe initialize the dma channel withthe timing ? */ 158 len+=2; 159 if (!(c & HPEE_DMA_MORE)) { 160 break; 161 } 162 } 163 164 return len; 165 } 166 167 static int configure_port(const unsigned char *buf, struct resource *io_parent, 168 char *board) 169 { 170 int len; 171 u_int8_t c; 172 int i; 173 struct resource *res; 174 int result; 175 176 len=0; 177 178 for (i=0;i<HPEE_PORT_MAX_ENT;i++) { 179 c = get_8(buf+len); 180 181 if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) { 182 res->name = board; 183 res->start = get_16(buf+len+1); 184 res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1; 185 res->flags = IORESOURCE_IO; 186 printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); 187 result = request_resource(io_parent, res); 188 if (result < 0) { 189 printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); 190 return result; 191 } 192 } 193 194 len+=3; 195 if (!(c & HPEE_PORT_MORE)) { 196 break; 197 } 198 } 199 200 return len; 201 } 202 203 204 /* byte 1 and 2 is the port number to write 205 * and at byte 3 the value to write starts. 206 * I assume that there are and- and or- masks 207 * here when HPEE_PORT_INIT_MASK is set but I have 208 * not yet encountered this. */ 209 static int configure_port_init(const unsigned char *buf) 210 { 211 int len=0; 212 u_int8_t c; 213 214 while (len<HPEE_PORT_INIT_MAX_LEN) { 215 int s=0; 216 c = get_8(buf+len); 217 218 switch (c & HPEE_PORT_INIT_WIDTH_MASK) { 219 case HPEE_PORT_INIT_WIDTH_BYTE: 220 s=1; 221 if (c & HPEE_PORT_INIT_MASK) { 222 printk(KERN_WARNING "port_init: unverified mask attribute\n"); 223 outb((inb(get_16(buf+len+1) & 224 get_8(buf+len+3)) | 225 get_8(buf+len+4)), get_16(buf+len+1)); 226 227 } else { 228 outb(get_8(buf+len+3), get_16(buf+len+1)); 229 230 } 231 break; 232 case HPEE_PORT_INIT_WIDTH_WORD: 233 s=2; 234 if (c & HPEE_PORT_INIT_MASK) { 235 printk(KERN_WARNING "port_init: unverified mask attribute\n"); 236 outw((inw(get_16(buf+len+1)) & 237 get_16(buf+len+3)) | 238 get_16(buf+len+5), 239 get_16(buf+len+1)); 240 } else { 241 outw(cpu_to_le16(get_16(buf+len+3)), get_16(buf+len+1)); 242 } 243 break; 244 case HPEE_PORT_INIT_WIDTH_DWORD: 245 s=4; 246 if (c & HPEE_PORT_INIT_MASK) { 247 printk(KERN_WARNING "port_init: unverified mask attribute\n"); 248 outl((inl(get_16(buf+len+1) & 249 get_32(buf+len+3)) | 250 get_32(buf+len+7)), get_16(buf+len+1)); 251 } else { 252 outl(cpu_to_le32(get_32(buf+len+3)), get_16(buf+len+1)); 253 } 254 255 break; 256 default: 257 printk(KERN_ERR "Invalid port init word %02x\n", c); 258 return 0; 259 } 260 261 if (c & HPEE_PORT_INIT_MASK) { 262 s*=2; 263 } 264 265 len+=s+3; 266 if (!(c & HPEE_PORT_INIT_MORE)) { 267 break; 268 } 269 } 270 271 return len; 272 } 273 274 static int configure_choise(const unsigned char *buf, u_int8_t *info) 275 { 276 int len; 277 278 /* theis record contain the value of the functions 279 * configuration choises and an info byte which 280 * describes which other records to expect in this 281 * function */ 282 len = get_8(buf); 283 *info=get_8(buf+len+1); 284 285 return len+2; 286 } 287 288 static int configure_type_string(const unsigned char *buf) 289 { 290 int len; 291 292 /* just skip past the type field */ 293 len = get_8(buf); 294 if (len > 80) { 295 printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); 296 } 297 298 return 1+len; 299 } 300 301 static int configure_function(const unsigned char *buf, int *more) 302 { 303 /* the init field seems to be a two-byte field 304 * which is non-zero if there are an other function following 305 * I think it is the length of the function def 306 */ 307 *more = get_16(buf); 308 309 return 2; 310 } 311 312 static int parse_slot_config(int slot, 313 const unsigned char *buf, 314 struct eeprom_eisa_slot_info *es, 315 struct resource *io_parent, 316 struct resource *mem_parent) 317 { 318 int res=0; 319 int function_len; 320 unsigned int pos=0; 321 unsigned int maxlen; 322 int num_func=0; 323 u_int8_t flags; 324 int p0; 325 326 char *board; 327 int id_string_used=0; 328 329 if (NULL == (board = kmalloc(8, GFP_KERNEL))) { 330 return -1; 331 } 332 print_eisa_id(board, es->eisa_slot_id); 333 printk(KERN_INFO "EISA slot %d: %s %s ", 334 slot, board, es->flags&HPEE_FLAG_BOARD_IS_ISA ? "ISA" : "EISA"); 335 336 maxlen = es->config_data_length < HPEE_MAX_LENGTH ? 337 es->config_data_length : HPEE_MAX_LENGTH; 338 while ((pos < maxlen) && (num_func <= es->num_functions)) { 339 pos+=configure_function(buf+pos, &function_len); 340 341 if (!function_len) { 342 break; 343 } 344 num_func++; 345 p0 = pos; 346 pos += configure_choise(buf+pos, &flags); 347 348 if (flags & HPEE_FUNCTION_INFO_F_DISABLED) { 349 /* function disabled, skip silently */ 350 pos = p0 + function_len; 351 continue; 352 } 353 if (flags & HPEE_FUNCTION_INFO_CFG_FREE_FORM) { 354 /* I have no idea how to handle this */ 355 printk("function %d have free-form configuration, skipping ", 356 num_func); 357 pos = p0 + function_len; 358 continue; 359 } 360 361 /* the ordering of the sections need 362 * more investigation. 363 * Currently I think that memory comaed before IRQ 364 * I assume the order is LSB to MSB in the 365 * info flags 366 * eg type, memory, irq, dma, port, HPEE_PORT_init 367 */ 368 369 if (flags & HPEE_FUNCTION_INFO_HAVE_TYPE) { 370 pos += configure_type_string(buf+pos); 371 } 372 373 if (flags & HPEE_FUNCTION_INFO_HAVE_MEMORY) { 374 id_string_used=1; 375 pos += configure_memory(buf+pos, mem_parent, board); 376 } 377 378 if (flags & HPEE_FUNCTION_INFO_HAVE_IRQ) { 379 pos += configure_irq(buf+pos); 380 } 381 382 if (flags & HPEE_FUNCTION_INFO_HAVE_DMA) { 383 pos += configure_dma(buf+pos); 384 } 385 386 if (flags & HPEE_FUNCTION_INFO_HAVE_PORT) { 387 id_string_used=1; 388 pos += configure_port(buf+pos, io_parent, board); 389 } 390 391 if (flags & HPEE_FUNCTION_INFO_HAVE_PORT_INIT) { 392 pos += configure_port_init(buf+pos); 393 } 394 395 if (p0 + function_len < pos) { 396 printk(KERN_ERR "eisa_enumerator: function %d length mis-match " 397 "got %d, expected %d\n", 398 num_func, pos-p0, function_len); 399 res=-1; 400 break; 401 } 402 pos = p0 + function_len; 403 } 404 printk("\n"); 405 if (!id_string_used) { 406 kfree(board); 407 } 408 409 if (pos != es->config_data_length) { 410 printk(KERN_ERR "eisa_enumerator: config data length mis-match got %d, expected %d\n", 411 pos, es->config_data_length); 412 res=-1; 413 } 414 415 if (num_func != es->num_functions) { 416 printk(KERN_ERR "eisa_enumerator: number of functions mis-match got %d, expected %d\n", 417 num_func, es->num_functions); 418 res=-2; 419 } 420 421 return res; 422 423 } 424 425 static int init_slot(int slot, struct eeprom_eisa_slot_info *es) 426 { 427 unsigned int id; 428 429 char id_string[8]; 430 431 if (!(es->slot_info&HPEE_SLOT_INFO_NO_READID)) { 432 /* try to read the id of the board in the slot */ 433 id = le32_to_cpu(inl(SLOT2PORT(slot)+EPI)); 434 435 if (0xffffffff == id) { 436 /* Maybe we didn't expect a card to be here... */ 437 if (es->eisa_slot_id == 0xffffffff) 438 return -1; 439 440 /* this board is not here or it does not 441 * support readid 442 */ 443 printk(KERN_ERR "EISA slot %d a configured board was not detected (", 444 slot); 445 446 print_eisa_id(id_string, es->eisa_slot_id); 447 printk(" expected %s)\n", id_string); 448 449 return -1; 450 451 } 452 if (es->eisa_slot_id != id) { 453 print_eisa_id(id_string, id); 454 printk(KERN_ERR "EISA slot %d id mis-match: got %s", 455 slot, id_string); 456 457 print_eisa_id(id_string, es->eisa_slot_id); 458 printk(" expected %s\n", id_string); 459 460 return -1; 461 462 } 463 } 464 465 /* now: we need to enable the board if 466 * it supports enabling and run through 467 * the port init sction if present 468 * and finally record any interrupt polarity 469 */ 470 if (es->slot_features & HPEE_SLOT_FEATURES_ENABLE) { 471 /* enable board */ 472 outb(0x01| inb(SLOT2PORT(slot)+EPI+4), 473 SLOT2PORT(slot)+EPI+4); 474 } 475 476 return 0; 477 } 478 479 480 int eisa_enumerator(unsigned long eeprom_addr, 481 struct resource *io_parent, struct resource *mem_parent) 482 { 483 int i; 484 struct eeprom_header *eh; 485 static char eeprom_buf[HPEE_MAX_LENGTH]; 486 487 for (i=0; i < HPEE_MAX_LENGTH; i++) { 488 eeprom_buf[i] = gsc_readb(eeprom_addr+i); 489 } 490 491 printk(KERN_INFO "Enumerating EISA bus\n"); 492 493 eh = (struct eeprom_header*)(eeprom_buf); 494 for (i=0;i<eh->num_slots;i++) { 495 struct eeprom_eisa_slot_info *es; 496 497 es = (struct eeprom_eisa_slot_info*) 498 (&eeprom_buf[HPEE_SLOT_INFO(i)]); 499 500 if (-1==init_slot(i+1, es)) { 501 continue; 502 } 503 504 if (es->config_data_offset < HPEE_MAX_LENGTH) { 505 if (parse_slot_config(i+1, &eeprom_buf[es->config_data_offset], 506 es, io_parent, mem_parent)) { 507 return -1; 508 } 509 } else { 510 printk (KERN_WARNING "EISA EEPROM offset 0x%x out of range\n",es->config_data_offset); 511 return -1; 512 } 513 } 514 return eh->num_slots; 515 } 516 517