in nubus.c [717:827]
static void __init nubus_add_board(int slot, int bytelanes)
{
struct nubus_board *board;
unsigned char *rp;
unsigned long dpat;
struct nubus_dir dir;
struct nubus_dirent ent;
int prev_resid = -1;
/* Move to the start of the format block */
rp = nubus_rom_addr(slot);
nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
/* Actually we should probably panic if this fails */
if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
return;
board->fblock = rp;
/* Dump the format block for debugging purposes */
pr_debug("Slot %X, format block at 0x%p:\n", slot, rp);
pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
rp = board->fblock;
board->slot = slot;
board->slot_addr = (unsigned long)nubus_slot_addr(slot);
board->doffset = nubus_get_rom(&rp, 4, bytelanes);
/* rom_length is *supposed* to be the total length of the
* ROM. In practice it is the "amount of ROM used to compute
* the CRC." So some jokers decide to set it to zero and
* set the crc to zero so they don't have to do any math.
* See the Performa 460 ROM, for example. Those Apple "engineers".
*/
board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
board->crc = nubus_get_rom(&rp, 4, bytelanes);
board->rev = nubus_get_rom(&rp, 1, bytelanes);
board->format = nubus_get_rom(&rp, 1, bytelanes);
board->lanes = bytelanes;
/* Directory offset should be small and negative... */
if (!(board->doffset & 0x00FF0000))
pr_warn("Slot %X: Dodgy doffset!\n", slot);
dpat = nubus_get_rom(&rp, 4, bytelanes);
if (dpat != NUBUS_TEST_PATTERN)
pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);
/*
* I wonder how the CRC is meant to work -
* any takers ?
* CSA: According to MAC docs, not all cards pass the CRC anyway,
* since the initial Macintosh ROM releases skipped the check.
*/
/* Set up the directory pointer */
board->directory = board->fblock;
nubus_move(&board->directory, nubus_expand32(board->doffset),
board->lanes);
nubus_get_root_dir(board, &dir);
/* We're ready to rock */
pr_debug("Slot %X resources:\n", slot);
/* Each slot should have one board resource and any number of
* functional resources. So we'll fill in some fields in the
* struct nubus_board from the board resource, then walk down
* the list of functional resources, spinning out a nubus_rsrc
* for each of them.
*/
if (nubus_readdir(&dir, &ent) == -1) {
/* We can't have this! */
pr_err("Slot %X: Board resource not found!\n", slot);
kfree(board);
return;
}
if (ent.type < 1 || ent.type > 127)
pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
board->procdir = nubus_proc_add_board(board);
nubus_get_board_resource(board, slot, &ent);
while (nubus_readdir(&dir, &ent) != -1) {
struct nubus_rsrc *fres;
fres = nubus_get_functional_resource(board, slot, &ent);
if (fres == NULL)
continue;
/* Resources should appear in ascending ID order. This sanity
* check prevents duplicate resource IDs.
*/
if (fres->resid <= prev_resid) {
kfree(fres);
continue;
}
prev_resid = fres->resid;
list_add_tail(&fres->list, &nubus_func_rsrcs);
}
if (nubus_device_register(board))
put_device(&board->dev);
}