in eisa_enumerator.c [312:423]
static int parse_slot_config(int slot,
const unsigned char *buf,
struct eeprom_eisa_slot_info *es,
struct resource *io_parent,
struct resource *mem_parent)
{
int res=0;
int function_len;
unsigned int pos=0;
unsigned int maxlen;
int num_func=0;
u_int8_t flags;
int p0;
char *board;
int id_string_used=0;
if (NULL == (board = kmalloc(8, GFP_KERNEL))) {
return -1;
}
print_eisa_id(board, es->eisa_slot_id);
printk(KERN_INFO "EISA slot %d: %s %s ",
slot, board, es->flags&HPEE_FLAG_BOARD_IS_ISA ? "ISA" : "EISA");
maxlen = es->config_data_length < HPEE_MAX_LENGTH ?
es->config_data_length : HPEE_MAX_LENGTH;
while ((pos < maxlen) && (num_func <= es->num_functions)) {
pos+=configure_function(buf+pos, &function_len);
if (!function_len) {
break;
}
num_func++;
p0 = pos;
pos += configure_choise(buf+pos, &flags);
if (flags & HPEE_FUNCTION_INFO_F_DISABLED) {
/* function disabled, skip silently */
pos = p0 + function_len;
continue;
}
if (flags & HPEE_FUNCTION_INFO_CFG_FREE_FORM) {
/* I have no idea how to handle this */
printk("function %d have free-form configuration, skipping ",
num_func);
pos = p0 + function_len;
continue;
}
/* the ordering of the sections need
* more investigation.
* Currently I think that memory comaed before IRQ
* I assume the order is LSB to MSB in the
* info flags
* eg type, memory, irq, dma, port, HPEE_PORT_init
*/
if (flags & HPEE_FUNCTION_INFO_HAVE_TYPE) {
pos += configure_type_string(buf+pos);
}
if (flags & HPEE_FUNCTION_INFO_HAVE_MEMORY) {
id_string_used=1;
pos += configure_memory(buf+pos, mem_parent, board);
}
if (flags & HPEE_FUNCTION_INFO_HAVE_IRQ) {
pos += configure_irq(buf+pos);
}
if (flags & HPEE_FUNCTION_INFO_HAVE_DMA) {
pos += configure_dma(buf+pos);
}
if (flags & HPEE_FUNCTION_INFO_HAVE_PORT) {
id_string_used=1;
pos += configure_port(buf+pos, io_parent, board);
}
if (flags & HPEE_FUNCTION_INFO_HAVE_PORT_INIT) {
pos += configure_port_init(buf+pos);
}
if (p0 + function_len < pos) {
printk(KERN_ERR "eisa_enumerator: function %d length mis-match "
"got %d, expected %d\n",
num_func, pos-p0, function_len);
res=-1;
break;
}
pos = p0 + function_len;
}
pr_cont("\n");
if (!id_string_used) {
kfree(board);
}
if (pos != es->config_data_length) {
printk(KERN_ERR "eisa_enumerator: config data length mis-match got %d, expected %d\n",
pos, es->config_data_length);
res=-1;
}
if (num_func != es->num_functions) {
printk(KERN_ERR "eisa_enumerator: number of functions mis-match got %d, expected %d\n",
num_func, es->num_functions);
res=-2;
}
return res;
}