blob: c6885f3a4b862fd03115fabfada295a95007dab3 [file] [log] [blame]
Nico Huber47cea9a2026-06-30 21:42:23 +02001/*
2 * This file is part of the flashprog project.
3 *
4 * Copyright (C) 2026 Nico Huber <nico.h@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <stddef.h>
18#include <stdint.h>
19
20#include "programmer.h"
21#include "platform/pci.h"
22#include "hwaccess_physmap.h"
23#include "programmer/physmap.h"
24
25#define PCI_VENDOR_ID_LSI 0x1000
26
27static const struct dev_entry scsi_lsi[] = {
28 {PCI_VENDOR_ID_LSI, 0x000f, OK, "LSI", "53c875" },
29
30 {0},
31};
32
33static const struct par_master par_master_scsilsi = {
34 .chip_readb = mmio_chip_readb,
35 .chip_readw = mmio_chip_readw,
36 .chip_readl = mmio_chip_readl,
37 .chip_readn = mmio_chip_readn,
38 .chip_writeb = mmio_chip_writeb,
39 .chip_writew = mmio_chip_writew,
40 .chip_writel = mmio_chip_writel,
41 .chip_writen = fallback_chip_writen,
42 .map_flash = physmap,
43 .unmap_flash = physunmap,
44};
45
46static int scsilsi_init(struct flashprog_programmer *const prog)
47{
48 struct pci_dev *const lsi = pcidev_init(scsi_lsi, PCI_BASE_ADDRESS_1);
49 if (!lsi)
50 return 1;
51
52 const uint16_t command = pci_read_word(lsi, PCI_COMMAND);
53 if (!(command & PCI_COMMAND_MEMORY)) {
54 msg_perr("Error: PCI memory access is disabled.\n");
55 return 1;
56 }
57
58 const uint32_t rom_base = pci_read_long(lsi, PCI_ROM_ADDRESS);
59 if (!rom_base) {
60 msg_perr("Error: PCI ROM base is not configured.\n");
61 return 1;
62 }
63 rpci_write_long(lsi, PCI_ROM_ADDRESS, rom_base | 1);
64
65 /* TODO: Use ROM BAR size detection. */
66
67 return register_par_master(&par_master_scsilsi, BUS_PARALLEL, rom_base & ~1u, 1*MiB, NULL);
68}
69
70const struct programmer_entry programmer_scsilsi = {
71 .name = "scsilsi",
72 .type = PCI,
73 .devs.dev = scsi_lsi,
74 .init = scsilsi_init,
75};