📄 sdladrv.c
字号:
* o position DPM window * o place boot instruction (jp addr) at cold boot entry point * o start CPU */static int sdla_start (sdlahw_t* hw, unsigned addr){ unsigned port = hw->port; unsigned char *bootp; int err, tmp, i; if (!port && (hw->type != SDLA_S514)) return -EFAULT; switch (hw->type) { case SDLA_S502A: bootp = hw->dpmbase; bootp += 0x66; break; case SDLA_S502E: case SDLA_S503: case SDLA_S507: case SDLA_S508: case SDLA_S514: bootp = hw->dpmbase; break; default: return -EINVAL; } err = sdla_mapmem(hw, 0); if (err) return err; writeb (0xC3, bootp); /* Z80: 'jp' opcode */ bootp ++; writew (addr, bootp); switch (hw->type) { case SDLA_S502A: _OUTB(port, 0x10); /* issue NMI to CPU */ hw->regs[0] = 0x10; break; case SDLA_S502E: _OUTB(port + 3, 0x01); /* start CPU */ hw->regs[3] = 0x01; for (i = 0; i < SDLA_IODELAY; ++i); if (_INB(port) & 0x01) { /* verify */ /* * Enabling CPU changes functionality of the * control register, so we have to reset its * mirror. */ _OUTB(port, 0); /* disable interrupts */ hw->regs[0] = 0; } else return -EIO; break; case SDLA_S503: tmp = hw->regs[0] | 0x09; /* set bits 0 and 3 */ _OUTB(port, tmp); hw->regs[0] = tmp; /* update mirror */ for (i = 0; i < SDLA_IODELAY; ++i); if (!(_INB(port) & 0x01)) /* verify */ return -EIO; break; case SDLA_S507: tmp = hw->regs[0] | 0x02; _OUTB(port, tmp); hw->regs[0] = tmp; /* update mirror */ for (i = 0; i < SDLA_IODELAY; ++i); if (!(_INB(port) & 0x04)) /* verify */ return -EIO; break; case SDLA_S508: tmp = hw->regs[0] | 0x02; _OUTB(port, tmp); hw->regs[0] = tmp; /* update mirror */ for (i = 0; i < SDLA_IODELAY; ++i); if (!(_INB(port + 1) & 0x02)) /* verify */ return -EIO; break; case SDLA_S514: writeb (S514_CPU_START, hw->vector); break; default: return -EINVAL; } return 0;}/*============================================================================ * Initialize S502A adapter. */static int init_s502a (sdlahw_t* hw){ unsigned port = hw->port; int tmp, i; if (!detect_s502a(port)) return -ENODEV; hw->regs[0] = 0x08; hw->regs[1] = 0xFF; /* Verify configuration options */ i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase)); if (i == 0) return -EINVAL; tmp = s502a_hmcr[i - 1]; switch (hw->dpmsize) { case 0x2000: tmp |= 0x01; break; case 0x10000L: break; default: return -EINVAL; } /* Setup dual-port memory window (this also enables memory access) */ _OUTB(port + 1, tmp); hw->regs[1] = tmp; hw->regs[0] = 0x08; return 0;}/*============================================================================ * Initialize S502E adapter. */static int init_s502e (sdlahw_t* hw){ unsigned port = hw->port; int tmp, i; if (!detect_s502e(port)) return -ENODEV; /* Verify configuration options */ i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); if (i == 0) return -EINVAL; tmp = s502e_hmcr[i - 1]; switch (hw->dpmsize) { case 0x2000: tmp |= 0x01; break; case 0x10000L: break; default: return -EINVAL; } /* Setup dual-port memory window */ _OUTB(port + 1, tmp); hw->regs[1] = tmp; /* Enable memory access */ _OUTB(port, 0x02); hw->regs[0] = 0x02; for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ return (_INB(port) & 0x02) ? 0 : -EIO;}/*============================================================================ * Initialize S503 adapter. * --------------------------------------------------------------------------- */static int init_s503 (sdlahw_t* hw){ unsigned port = hw->port; int tmp, i; if (!detect_s503(port)) return -ENODEV; /* Verify configuration options */ i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); if (i == 0) return -EINVAL; tmp = s502e_hmcr[i - 1]; switch (hw->dpmsize) { case 0x2000: tmp |= 0x01; break; case 0x10000L: break; default: return -EINVAL; } /* Setup dual-port memory window */ _OUTB(port + 1, tmp); hw->regs[1] = tmp; /* Enable memory access */ _OUTB(port, 0x02); hw->regs[0] = 0x02; /* update mirror */ return 0;}/*============================================================================ * Initialize S507 adapter. */static int init_s507 (sdlahw_t* hw){ unsigned port = hw->port; int tmp, i; if (!detect_s507(port)) return -ENODEV; /* Verify configuration options */ i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase)); if (i == 0) return -EINVAL; tmp = s507_hmcr[i - 1]; switch (hw->dpmsize) { case 0x2000: tmp |= 0x01; break; case 0x10000L: break; default: return -EINVAL; } /* Enable adapter's logic */ _OUTB(port, 0x01); hw->regs[0] = 0x01; for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (!(_INB(port) & 0x20)) return -EIO; /* Setup dual-port memory window */ _OUTB(port + 1, tmp); hw->regs[1] = tmp; /* Enable memory access */ tmp = hw->regs[0] | 0x04; if (hw->irq) { i = get_option_index(s508_irq_options, hw->irq); if (i) tmp |= s507_irqmask[i - 1]; } _OUTB(port, tmp); hw->regs[0] = tmp; /* update mirror */ for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ return (_INB(port) & 0x08) ? 0 : -EIO;}/*============================================================================ * Initialize S508 adapter. */static int init_s508 (sdlahw_t* hw){ unsigned port = hw->port; int tmp, i; if (!detect_s508(port)) return -ENODEV; /* Verify configuration options */ i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); if (i == 0) return -EINVAL; /* Setup memory configuration */ tmp = s508_hmcr[i - 1]; _OUTB(port + 1, tmp); hw->regs[1] = tmp; /* Enable memory access */ _OUTB(port, 0x04); hw->regs[0] = 0x04; /* update mirror */ for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ return (_INB(port + 1) & 0x04) ? 0 : -EIO;}/*============================================================================ * Detect S502A adapter. * Following tests are used to detect S502A adapter: * 1. All registers other than status (BASE) should read 0xFF * 2. After writing 00001000b to control register, status register should * read 01000000b. * 3. After writing 0 to control register, status register should still * read 01000000b. * 4. After writing 00000100b to control register, status register should * read 01000100b. * Return 1 if detected o.k. or 0 if failed. * Note: This test is destructive! Adapter will be left in shutdown * state after the test. */static int detect_s502a (int port){ int i, j; if (!get_option_index(s502_port_options, port)) return 0; for (j = 1; j < SDLA_MAXIORANGE; ++j) { if (_INB(port + j) != 0xFF) return 0; for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ } _OUTB(port, 0x08); /* halt CPU */ _OUTB(port, 0x08); _OUTB(port, 0x08); for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (_INB(port) != 0x40) return 0; _OUTB(port, 0x00); for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (_INB(port) != 0x40) return 0; _OUTB(port, 0x04); for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (_INB(port) != 0x44) return 0; /* Reset adapter */ _OUTB(port, 0x08); _OUTB(port, 0x08); _OUTB(port, 0x08); _OUTB(port + 1, 0xFF); return 1;}/*============================================================================ * Detect S502E adapter. * Following tests are used to verify adapter presence: * 1. All registers other than status (BASE) should read 0xFF. * 2. After writing 0 to CPU control register (BASE+3), status register * (BASE) should read 11111000b. * 3. After writing 00000100b to port BASE (set bit 2), status register * (BASE) should read 11111100b. * Return 1 if detected o.k. or 0 if failed. * Note: This test is destructive! Adapter will be left in shutdown * state after the test. */static int detect_s502e (int port){ int i, j; if (!get_option_index(s502_port_options, port)) return 0; for (j = 1; j < SDLA_MAXIORANGE; ++j) { if (_INB(port + j) != 0xFF) return 0; for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ } _OUTB(port + 3, 0); /* CPU control reg. */ for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (_INB(port) != 0xF8) /* read status */ return 0; _OUTB(port, 0x04); /* set bit 2 */ for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (_INB(port) != 0xFC) /* verify */ return 0; /* Reset adapter */ _OUTB(port, 0); return 1;}/*============================================================================ * Detect s503 adapter. * Following tests are used to verify adapter presence: * 1. All registers other than status (BASE) should read 0xFF. * 2. After writing 0 to control register (BASE), status register (BASE) * should read 11110000b. * 3. After writing 00000100b (set bit 2) to control register (BASE), * status register should read 11110010b. * Return 1 if detected o.k. or 0 if failed. * Note: This test is destructive! Adapter will be left in shutdown * state after the test. */static int detect_s503 (int port){ int i, j; if (!get_option_index(s503_port_options, port)) return 0; for (j = 1; j < SDLA_MAXIORANGE; ++j) { if (_INB(port + j) != 0xFF) return 0; for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ } _OUTB(port, 0); /* reset control reg.*/ for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (_INB(port) != 0xF0) /* read status */ return 0; _OUTB(port, 0x04); /* set bit 2 */ for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if (_INB(port) != 0xF2) /* verify */ return 0; /* Reset adapter */ _OUTB(port, 0); return 1;}/*============================================================================ * Detect s507 adapter. * Following tests are used to detect s507 adapter: * 1. All ports should read the same value. * 2. After writing 0x00 to control register, status register should read * ?011000?b. * 3. After writing 0x01 to control register, status register should read * ?011001?b. * Return 1 if detected o.k. or 0 if failed. * Note: This test is destructive! Adapter will be left in shutdown * state after the test. */static int detect_s507 (int port){ int tmp, i, j; if (!get_option_index(s508_port_options, port)) return 0; tmp = _INB(port); for (j = 1; j < S507_IORANGE; ++j) { if (_INB(port + j) != tmp) return 0; for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ } _OUTB(port, 0x00); for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if ((_INB(port) & 0x7E) != 0x30) return 0; _OUTB(port, 0x01); for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ if ((_INB(port) & 0x7E) != 0x32) return 0; /* Reset adapter */ _OUTB(port, 0x00); return 1;}/*============================================================================ * Detect s508 adapter. * Following tests are used to detect s508 adapter:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -