1 /* 2 * This file is part of the flashrom project. 3 * 4 * Copyright (C) 2009 Joerg Fischer <turboj@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 #if defined(__i386__) || defined(__x86_64__) 18 19 #include <stdlib.h> 20 #include "flash.h" 21 #include "programmer.h" 22 #include "hwaccess.h" 23 24 #define PCI_VENDOR_ID_REALTEK 0x10ec 25 #define PCI_VENDOR_ID_SMC1211 0x1113 26 27 static uint32_t io_base_addr = 0; 28 static int bios_rom_addr, bios_rom_data; 29 30 const struct dev_entry nics_realtek[] = { 31 {0x10ec, 0x8139, OK, "Realtek", "RTL8139/8139C/8139C+"}, 32 {0x10ec, 0x8169, NT, "Realtek", "RTL8169"}, 33 {0x1113, 0x1211, OK, "SMC", "1211TX"}, /* RTL8139 clone */ 34 35 {0}, 36 }; 37 38 static void nicrealtek_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr); 39 static uint8_t nicrealtek_chip_readb(const struct flashctx *flash, const chipaddr addr); 40 static const struct par_master par_master_nicrealtek = { 41 .chip_readb = nicrealtek_chip_readb, 42 .chip_readw = fallback_chip_readw, 43 .chip_readl = fallback_chip_readl, 44 .chip_readn = fallback_chip_readn, 45 .chip_writeb = nicrealtek_chip_writeb, 46 .chip_writew = fallback_chip_writew, 47 .chip_writel = fallback_chip_writel, 48 .chip_writen = fallback_chip_writen, 49 }; 50 51 static int nicrealtek_shutdown(void *data) 52 { 53 /* FIXME: We forgot to disable software access again. */ 54 return 0; 55 } 56 57 int nicrealtek_init(void) 58 { 59 struct pci_dev *dev = NULL; 60 61 if (rget_io_perms()) 62 return 1; 63 64 dev = pcidev_init(nics_realtek, PCI_BASE_ADDRESS_0); 65 if (!dev) 66 return 1; 67 parse_voltage(char * voltage)68 io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 69 if (!io_base_addr) 70 return 1; 71 72 /* Beware, this ignores the vendor ID! */ 73 switch (dev->device_id) { 74 case 0x8139: /* RTL8139 */ 75 case 0x1211: /* SMC 1211TX */ 76 default: 77 bios_rom_addr = 0xD4; 78 bios_rom_data = 0xD7; 79 break; 80 case 0x8169: /* RTL8169 */ 81 bios_rom_addr = 0x30; 82 bios_rom_data = 0x33; 83 break; 84 } 85 86 if (register_shutdown(nicrealtek_shutdown, NULL)) 87 return 1; 88 89 register_par_master(&par_master_nicrealtek, BUS_PARALLEL); 90 91 return 0; 92 } 93 94 static void nicrealtek_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) 95 { 96 /* Output addr and data, set WE to 0, set OE to 1, set CS to 0, 97 * enable software access. 98 */ 99 OUTL(((uint32_t)addr & 0x01FFFF) | 0x0A0000 | (val << 24), 100 io_base_addr + bios_rom_addr); 101 /* Output addr and data, set WE to 1, set OE to 1, set CS to 1, 102 * enable software access. 103 */ 104 OUTL(((uint32_t)addr & 0x01FFFF) | 0x1E0000 | (val << 24), 105 io_base_addr + bios_rom_addr); 106 } 107 108 static uint8_t nicrealtek_chip_readb(const struct flashctx *flash, const chipaddr addr) 109 { 110 uint8_t val; 111 112 /* FIXME: Can we skip reading the old data and simply use 0? */ 113 /* Read old data. */ 114 val = INB(io_base_addr + bios_rom_data); ni845x_report_error(const char * const func,const int32 err)115 /* Output new addr and old data, set WE to 1, set OE to 0, set CS to 0, 116 * enable software access. 117 */ 118 OUTL(((uint32_t)addr & 0x01FFFF) | 0x060000 | (val << 24), 119 io_base_addr + bios_rom_addr); 120 121 /* Read new data. */ 122 val = INB(io_base_addr + bios_rom_data); ni845x_report_warning(const char * const func,const int32 err)123 /* Output addr and new data, set WE to 1, set OE to 1, set CS to 1, 124 * enable software access. 125 */ 126 OUTL(((uint32_t)addr & 0x01FFFF) | 0x1E0000 | (val << 24), 127 io_base_addr + bios_rom_addr); 128 129 return val; 130 } 131 132 #else 133 #error PCI port I/O access is not supported on this architecture yet. 134 #endif ni845x_spi_open(const char * serial,uInt32 * return_handle)135