📄 machdep.c
字号:
/* * TURBOchannel autoconf procedure. Finds in one sweep what is * hanging on the bus and fills in the tc_slot_info array. * This is only the first part of the autoconf scheme, at this * time we are basically only looking for a graphics board to * use as system console (all workstations). */voidtc_find_all_options(){ register int i; u_long addr; int found; register tc_option_t *sl; struct drivers_map *map; register struct pmax_ctlr *cp; register struct driver *drp; /* * Take a look at the bus */ bzero(tc_slot_info, sizeof(tc_slot_info)); for (i = tc_max_slot; i >= tc_min_slot;) { addr = MACH_PHYS_TO_UNCACHED(tc_slot_phys_base[i]); found = tc_probe_slot(addr, &tc_slot_info[i]); if (found) { /* * Found a slot, make a note of it */ tc_slot_info[i].present = 1; tc_slot_info[i].k1seg_address = addr; } i -= tc_slot_info[i].slot_size; } /* * Some slots (e.g. the system slot on 3max) might require * hand-filling. If so, do it now. */ if (tc_slot_hand_fill) (*tc_slot_hand_fill) (tc_slot_info); /* * Now for each alive slot see if we have a device driver that * handles it. This is done in "priority order", meaning that * always present devices are at higher slot numbers on all * current TC machines, and option slots are at lowest numbers. */ for (i = TC_MAX_LOGICAL_SLOTS - 1; i >= 0; i--) { sl = &tc_slot_info[i]; if (!sl->present) continue; found = FALSE; for (map = tc_drivers_map; map->driver_name; map++) { if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN)) continue; sl->driver_name = map->driver_name; found = TRUE; break; } if (!found) { printf("%s %s %s\n", "Cannot associate a device driver to", sl->module_name, ". Will (try to) ignore it."); sl->present = 0; continue; } /* * Find the device driver entry and fill in the address. */ for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) { if (strcmp(drp->d_name, map->driver_name)) continue; if (cp->pmax_alive) continue; if (cp->pmax_addr == (char *)QUES) { cp->pmax_addr = (char *)sl->k1seg_address; cp->pmax_pri = i; /* * Only enable interrupts if there is an * interrupt handler for it. (e.g., PMAG-BA * can't disable the vertical retrace interrupt * and we might want to ignore it). */ if (drp->d_intr) (*tc_enable_interrupt)(i, 1); cp->pmax_alive = 1; break; } if (cp->pmax_addr != (char *)sl->k1seg_address) { cp->pmax_addr = (char *)QUES; printf("%s: device not at configued address (expected at %x, found at %x)\n", drp->d_name, cp->pmax_addr, sl->k1seg_address); } } }}/* * Probe a slot in the TURBOchannel. Return TRUE if a valid option * is present, FALSE otherwise. A side-effect is to fill the slot * descriptor with the size of the option, whether it is * recognized or not. */inttc_probe_slot(addr, slot) caddr_t addr; tc_option_t *slot;{ int i; static unsigned tc_offset_rom[] = { TC_OFF_PROTO_ROM, TC_OFF_ROM };#define TC_N_OFFSETS sizeof(tc_offset_rom)/sizeof(unsigned) slot->slot_size = 1; for (i = 0; i < TC_N_OFFSETS; i++) { if (badaddr(addr + tc_offset_rom[i], 4)) continue; /* complain only on last chance */ if (tc_identify_option((tc_rommap_t *)(addr + tc_offset_rom[i]), slot, i == (TC_N_OFFSETS-1))) return (1); } return (0);#undef TC_N_OFFSETS}/* * Enable/Disable interrupts for a TURBOchannel slot. */voidkn02_enable_intr(slotno, on) register int slotno; int on;{ register volatile int *p_csr = (volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR); int csr; int s; slotno = 1 << (slotno + KN02_CSR_IOINTEN_SHIFT); s = Mach_spl0(); csr = *p_csr & ~(KN02_CSR_WRESERVED | 0xFF); if (on) *p_csr = csr | slotno; else *p_csr = csr & ~slotno; splx(s);}/* * Object: * kmin_enable_intr EXPORTED function * * Enable/Disable interrupts from a TURBOchannel slot. * * We pretend we actually have 8 slots even if we really have * only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to * slots 3-7 (see kmin_slot_hand_fill). */voidkmin_enable_intr(slotno, on) register unsigned int slotno; int on;{ register unsigned mask; switch (slotno) { case 0: case 1: case 2: return; case KMIN_SCSI_SLOT: mask = (KMIN_INTR_SCSI | KMIN_INTR_SCSI_PTR_LOAD | KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E); break; case KMIN_LANCE_SLOT: mask = KMIN_INTR_LANCE; break; case KMIN_SCC0_SLOT: mask = KMIN_INTR_SCC_0; break; case KMIN_SCC1_SLOT: mask = KMIN_INTR_SCC_1; break; case KMIN_ASIC_SLOT: mask = KMIN_INTR_ASIC; break; default: return; } if (on) kmin_tc3_imask |= mask; else kmin_tc3_imask &= ~mask;}/* * Object: * xine_enable_intr EXPORTED function * * Enable/Disable interrupts from a TURBOchannel slot. * * We pretend we actually have 11 slots even if we really have * only 3: TCslots 0-1 maps to slots 0-1, TCslot 2 is used for * the system (TCslot3), TCslot3 maps to slots 3-10 * (see xine_slot_hand_fill). * Note that all these interrupts come in via the IMR. */voidxine_enable_intr(slotno, on) register unsigned int slotno; int on;{ register unsigned mask; switch (slotno) { case 0: /* a real slot, but */ mask = XINE_INTR_TC_0; break; case 1: /* a real slot, but */ mask = XINE_INTR_TC_1; break; case XINE_FLOPPY_SLOT: mask = XINE_INTR_FLOPPY; break; case XINE_SCSI_SLOT: mask = (XINE_INTR_SCSI | XINE_INTR_SCSI_PTR_LOAD | XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E); break; case XINE_LANCE_SLOT: mask = XINE_INTR_LANCE; break; case XINE_SCC0_SLOT: mask = XINE_INTR_SCC_0; break; case XINE_DTOP_SLOT: mask = XINE_INTR_DTOP_RX; break; case XINE_ISDN_SLOT: mask = XINE_INTR_ISDN; break; case XINE_ASIC_SLOT: mask = XINE_INTR_ASIC; break; default: return;/* ignore */ } if (on) xine_tc3_imask |= mask; else xine_tc3_imask &= ~mask;}#ifdef DS5000_240/* * UNTESTED!! * Object: * kn03_enable_intr EXPORTED function * * Enable/Disable interrupts from a TURBOchannel slot. * * We pretend we actually have 8 slots even if we really have * only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to * slots 3-7 (see kn03_slot_hand_fill). */voidkn03_enable_intr(slotno, on) register unsigned int slotno; int on;{ register unsigned mask; switch (slotno) { case 0: mask = KN03_INTR_TC_0; break; case 1: mask = KN03_INTR_TC_1; break; case 2: mask = KN03_INTR_TC_2; break; case KN03_SCSI_SLOT: mask = (KN03_INTR_SCSI | KN03_INTR_SCSI_PTR_LOAD | KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E); break; case KN03_LANCE_SLOT: mask = KN03_INTR_LANCE; break; case KN03_SCC0_SLOT: mask = KN03_INTR_SCC_0; break; case KN03_SCC1_SLOT: mask = KN03_INTR_SCC_1; break; case KN03_ASIC_SLOT: mask = KN03_INTR_ASIC; break; default: return; } if (on) kn03_tc3_imask |= mask; else kn03_tc3_imask &= ~mask;}#endif /* DS5000_240 *//* * Object: * kn02_slot_hand_fill EXPORTED function * * Fill in by hand the info for TC slots that are non-standard. * This is basically just the system slot on a 3max, it does not * look to me like it follows the TC rules although some of the * required info is indeed there. * */voidkn02_slot_hand_fill(slot) tc_option_t *slot;{ slot[7].present = 1; slot[7].slot_size = 1; slot[7].rom_width = 1;#if unsafe bcopy(0xbffc0410, slot[7].module_name, TC_ROM_LLEN+1);#endif bcopy("KN02 ", slot[7].module_name, TC_ROM_LLEN+1); bcopy("DEC xxxx", slot[7].module_id, TC_ROM_LLEN+1); slot[7].k1seg_address = MACH_PHYS_TO_UNCACHED(KN02_SYS_DZ);}/* * Object: * kmin_slot_hand_fill EXPORTED function * * Fill in by hand the info for TC slots that are non-standard. * This is the system slot on a 3min, which we think of as a * set of non-regular size TC slots. * */voidkmin_slot_hand_fill(slot) tc_option_t *slot;{ register int i; for (i = KMIN_SCSI_SLOT; i < KMIN_ASIC_SLOT+1; i++) { slot[i].present = 1; slot[i].slot_size = 1; slot[i].rom_width = 1; slot[i].unit = 0; bcopy("DEC KMIN", slot[i].module_id, TC_ROM_LLEN+1); } /* scsi */ bcopy("PMAZ-AA ", slot[KMIN_SCSI_SLOT].module_name, TC_ROM_LLEN+1); slot[KMIN_SCSI_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCSI); /* lance */ bcopy("PMAD-AA ", slot[KMIN_LANCE_SLOT].module_name, TC_ROM_LLEN+1); slot[KMIN_LANCE_SLOT].k1seg_address = 0; /* scc */ bcopy("Z8530 ", slot[KMIN_SCC0_SLOT].module_name, TC_ROM_LLEN+1); slot[KMIN_SCC0_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_0); slot[KMIN_SCC1_SLOT].unit = 1; bcopy("Z8530 ", slot[KMIN_SCC1_SLOT].module_name, TC_ROM_LLEN+1); slot[KMIN_SCC1_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_1); /* asic */ bcopy("ASIC ", slot[KMIN_ASIC_SLOT].module_name, TC_ROM_LLEN+1); slot[KMIN_ASIC_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC); asic_init(0);}/* * Object: * xine_slot_hand_fill EXPORTED function * * Fill in by hand the info for TC slots that are non-standard. * This is the system slot on a 3min, which we think of as a * set of non-regular size TC slots. * */voidxine_slot_hand_fill(slot) tc_option_t *slot;{ register int i; for (i = XINE_FLOPPY_SLOT; i < XINE_FRC_SLOT+1; i++) { slot[i].present = 1; slot[i].slot_size = 1; slot[i].rom_width = 1; slot[i].unit = 0; bcopy("DEC XINE", slot[i].module_id, TC_ROM_LLEN+1); } /* floppy */ bcopy("XINE-FDC", slot[XINE_FLOPPY_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_FLOPPY_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_SYS_FLOPPY); /* scsi */ bcopy("PMAZ-AA ", slot[XINE_SCSI_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_SCSI_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_SYS_SCSI); /* lance */ bcopy("PMAD-AA ", slot[XINE_LANCE_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_LANCE_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_SYS_LANCE); /* scc */ bcopy("Z8530 ", slot[XINE_SCC0_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_SCC0_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_SYS_SCC_0); /* Desktop */ bcopy("DTOP ", slot[XINE_DTOP_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_DTOP_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_SYS_DTOP+0x20000); /* why? */ /* ISDN */ bcopy("AMD79c30", slot[XINE_ISDN_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_ISDN_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_SYS_ISDN); /* Video */ bcopy("PMAG-DV ", slot[XINE_CFB_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_CFB_SLOT].k1seg_address = MACH_PHYS_TO_CACHED(XINE_PHYS_CFB_START); /* asic */ bcopy("ASIC ", slot[XINE_ASIC_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_ASIC_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC); /* free-running counter (high resolution mapped time) */ bcopy("XINE-FRC", slot[XINE_FRC_SLOT].module_name, TC_ROM_LLEN+1); slot[XINE_FRC_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(XINE_REG_FCTR); asic_init(1);}#ifdef DS5000_240/* * UNTESTED!! * Object: * kn03_slot_hand_fill EXPORTED function * * Fill in by hand the info for TC slots that are non-standard. * This is the system slot on a 3max+, which we think of as a * set of non-regular size TC slots. * */voidkn03_slot_hand_fill(slot) tc_option_t *slot;{ register int i; for (i = KN03_SCSI_SLOT; i < KN03_ASIC_SLOT+1; i++) { slot[i].present = 1; slot[i].slot_size = 1; slot[i].rom_width = 1; slot[i].unit = 0; bcopy("DEC KN03", slot[i].module_id, TC_ROM_LLEN+1); } /* scsi */ bcopy("PMAZ-AA ", slot[KN03_SCSI_SLOT].module_name, TC_ROM_LLEN+1); slot[KN03_SCSI_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KN03_SYS_SCSI); /* lance */ bcopy("PMAD-AA ", slot[KN03_LANCE_SLOT].module_name, TC_ROM_LLEN+1); slot[KN03_LANCE_SLOT].k1seg_address = 0; /* scc */ bcopy("Z8530 ", slot[KN03_SCC0_SLOT].module_name, TC_ROM_LLEN+1); slot[KN03_SCC0_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_0); slot[KN03_SCC1_SLOT].unit = 1; bcopy("Z8530 ", slot[KN03_SCC1_SLOT].module_name, TC_ROM_LLEN+1); slot[KN03_SCC1_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_1); /* asic */ bcopy("ASIC ", slot[KN03_ASIC_SLOT].module_name, TC_ROM_LLEN+1); slot[KN03_ASIC_SLOT].k1seg_address = MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC); asic_init(0);}#endif /* DS5000_240 *//* * Initialize the I/O asic */static voidasic_init(isa_maxine) int isa_maxine;{ volatile u_int *decoder; /* These are common between 3min and maxine */ decoder = (volatile u_int *)ASIC_REG_LANCE_DECODE(asic_base); *decoder = KMIN_LANCE_CONFIG;}#endif /* DS5000 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -