diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/microcode/typhoon/3c990-license | 31 | ||||
-rw-r--r-- | sys/dev/microcode/typhoon/Makefile | 27 | ||||
-rw-r--r-- | sys/dev/microcode/typhoon/build.c | 38 | ||||
-rw-r--r-- | sys/dev/pci/files.pci | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_txp.c | 225 |
5 files changed, 232 insertions, 93 deletions
diff --git a/sys/dev/microcode/typhoon/3c990-license b/sys/dev/microcode/typhoon/3c990-license new file mode 100644 index 00000000000..5dbbdc27fe8 --- /dev/null +++ b/sys/dev/microcode/typhoon/3c990-license @@ -0,0 +1,31 @@ + * Copyright 1999-2002 3Com Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms of the 3CR990img.h microcode + * software are permitted provided that the following conditions are met: + * 1. Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of 3Com may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY 3COM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * USER ACKNOWLEDGES AND AGREES THAT PURCHASE OR USE OF THE 3CR990img.h MICROCODE + * SOFTWARE WILL NOT CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, + * ESTOPPEL, OR OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT, + * TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN ANY OTHER + * 3COM HARDWARE OR SOFTWARE EITHER SOLELY OR IN COMBINATION WITH THE 3CR990img.h + * microcode SOFTWARE + +This license applies to the 3c990 firmware for the Typhoon adapters. diff --git a/sys/dev/microcode/typhoon/Makefile b/sys/dev/microcode/typhoon/Makefile new file mode 100644 index 00000000000..78e5618ec43 --- /dev/null +++ b/sys/dev/microcode/typhoon/Makefile @@ -0,0 +1,27 @@ +# $OpenBSD: Makefile,v 1.1 2004/12/14 01:50:42 deraadt Exp $ + +NOPROG= +NOMAN= + +# PCI capable systems only +.if (${MACHINE} == "i386") || (${MACHINE} == "amd64") || \ + (${MACHINE} == "alpha") || (${MACHINE} == "sparc64") || \ + (${MACHINE_ARCH} == "powerpc") || (${MACHINE} == "cats") || \ + (${MACHINE} == "hppa") || (${MACHINE} == "sgi") + +FIRM= 3c990 + +CLEANFILES+= build + +all: build + ${.OBJDIR}/build + +afterinstall: + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \ + ${FIRM} ${DESTDIR}/etc/firmware + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \ + ${.CURDIR}/3c990-license ${DESTDIR}/etc/firmware +.endif + +.include <bsd.prog.mk> + diff --git a/sys/dev/microcode/typhoon/build.c b/sys/dev/microcode/typhoon/build.c new file mode 100644 index 00000000000..6faba4609bf --- /dev/null +++ b/sys/dev/microcode/typhoon/build.c @@ -0,0 +1,38 @@ +/* $OpenBSD: build.c,v 1.1 2004/12/14 01:50:42 deraadt Exp $ */ + +/* + * Copyright (c) 2004 Theo de Raadt <deraadt@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <sys/types.h> +#include <fcntl.h> + +#include "3c990img.h" +#define FILENAME "3c990" + +int +main(int argc, char *argv[]) +{ + int i; + int fd; + + printf("creating %s length %d\n", FILENAME, sizeof tc990image); + fd = open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd == -1) + err(1, "%s", FILENAME); + + write(fd, tc990image, sizeof tc990image); + close(fd); + return 0; +} diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 12404c2afa6..0084a7e77a4 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.165 2004/12/01 01:28:59 pvalchev Exp $ +# $OpenBSD: files.pci,v 1.166 2004/12/14 01:50:42 deraadt Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -130,7 +130,7 @@ attach esa at pci file dev/pci/esa.c esa # Yamaha YMF Audio -device yds { }: audio, auconv, mulaw, ac97 +device yds { }: audio, auconv, mulaw, ac97, firmload attach yds at pci file dev/pci/yds.c yds diff --git a/sys/dev/pci/if_txp.c b/sys/dev/pci/if_txp.c index 61aba5a8a17..807ebe21655 100644 --- a/sys/dev/pci/if_txp.c +++ b/sys/dev/pci/if_txp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_txp.c,v 1.73 2004/09/23 17:45:16 brad Exp $ */ +/* $OpenBSD: if_txp.c,v 1.74 2004/12/14 01:50:42 deraadt Exp $ */ /* * Copyright (c) 2001 @@ -76,8 +76,6 @@ #include <dev/pci/if_txpreg.h> -#include <dev/microcode/typhoon/3c990img.h> - /* * These currently break the 3c990 firmware, hopefully will be resolved * at some point. @@ -87,6 +85,7 @@ int txp_probe(struct device *, void *, void *); void txp_attach(struct device *, struct device *, void *); +void txp_attachhook(void *vsc); int txp_intr(void *); void txp_tick(void *); void txp_shutdown(void *); @@ -101,7 +100,7 @@ int txp_reset_adapter(struct txp_softc *); int txp_download_fw(struct txp_softc *); int txp_download_fw_wait(struct txp_softc *); int txp_download_fw_section(struct txp_softc *, - struct txp_fw_section_header *, int); + struct txp_fw_section_header *, int, u_char *, size_t); int txp_alloc_rings(struct txp_softc *); void txp_dma_free(struct txp_softc *, struct txp_dma_alloc *); int txp_dma_malloc(struct txp_softc *, bus_size_t, struct txp_dma_alloc *, int); @@ -158,78 +157,44 @@ txp_probe(parent, match, aux) } void -txp_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +txp_attachhook(void *vsc) { - struct txp_softc *sc = (struct txp_softc *)self; - struct pci_attach_args *pa = aux; - pci_chipset_tag_t pc = pa->pa_pc; - pci_intr_handle_t ih; - const char *intrstr = NULL; + struct txp_softc *sc = vsc; struct ifnet *ifp = &sc->sc_arpcom.ac_if; - bus_size_t iosize; - u_int32_t command; u_int16_t p1; u_int32_t p2; + int s; - sc->sc_cold = 1; - - command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); - - if (!(command & PCI_COMMAND_MASTER_ENABLE)) { - printf(": failed to enable bus mastering\n"); - return; - } + s = splnet(); + printf("%s: ", sc->sc_dev.dv_xname); - if (!(command & PCI_COMMAND_MEM_ENABLE)) { - printf(": failed to enable memory mapping\n"); - return; - } - if (pci_mapreg_map(pa, TXP_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0, - &sc->sc_bt, &sc->sc_bh, NULL, &iosize, 0)) { - printf(": can't map mem space %d\n", 0); + if (txp_chip_init(sc)) { + printf("failed chip init\n"); + splx(s); return; } - sc->sc_dmat = pa->pa_dmat; - - /* - * Allocate our interrupt. - */ - if (pci_intr_map(pa, &ih)) { - printf(": couldn't map interrupt\n"); + if (txp_download_fw(sc)) { + splx(s); return; } - intrstr = pci_intr_string(pc, ih); - sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, txp_intr, sc, - self->dv_xname); - if (sc->sc_ih == NULL) { - printf(": couldn't establish interrupt"); - if (intrstr != NULL) - printf(" at %s", intrstr); - printf("\n"); + if (txp_alloc_rings(sc)) { + splx(s); return; } - printf(": %s", intrstr); - - if (txp_chip_init(sc)) - return; - - if (txp_download_fw(sc)) - return; - - if (txp_alloc_rings(sc)) - return; if (txp_command(sc, TXP_CMD_MAX_PKT_SIZE_WRITE, TXP_MAX_PKTLEN, 0, 0, - NULL, NULL, NULL, 1)) + NULL, NULL, NULL, 1)) { + splx(s); return; + } if (txp_command(sc, TXP_CMD_STATION_ADDRESS_READ, 0, 0, 0, - &p1, &p2, NULL, 1)) + &p1, &p2, NULL, 1)) { + splx(s); return; + } txp_set_filter(sc); @@ -242,7 +207,7 @@ txp_attach(parent, self, aux) sc->sc_arpcom.ac_enaddr[4] = ((u_int8_t *)&p2)[1]; sc->sc_arpcom.ac_enaddr[5] = ((u_int8_t *)&p2)[0]; - printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); + printf("address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); sc->sc_cold = 0; ifmedia_init(&sc->sc_ifmedia, 0, txp_ifmedia_upd, txp_ifmedia_sts); @@ -281,6 +246,68 @@ txp_attach(parent, self, aux) ether_ifattach(ifp); shutdownhook_establish(txp_shutdown, sc); + splx(s); +} + +void +txp_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct txp_softc *sc = (struct txp_softc *)self; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pci_intr_handle_t ih; + const char *intrstr = NULL; + bus_size_t iosize; + u_int32_t command; + + sc->sc_cold = 1; + + command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); + + if (!(command & PCI_COMMAND_MASTER_ENABLE)) { + printf(": failed to enable bus mastering\n"); + return; + } + + if (!(command & PCI_COMMAND_MEM_ENABLE)) { + printf(": failed to enable memory mapping\n"); + return; + } + if (pci_mapreg_map(pa, TXP_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0, + &sc->sc_bt, &sc->sc_bh, NULL, &iosize, 0)) { + printf(": can't map mem space %d\n", 0); + return; + } + + sc->sc_dmat = pa->pa_dmat; + + /* + * Allocate our interrupt. + */ + if (pci_intr_map(pa, &ih)) { + printf(": couldn't map interrupt\n"); + return; + } + + intrstr = pci_intr_string(pc, ih); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, txp_intr, sc, + self->dv_xname); + if (sc->sc_ih == NULL) { + printf(": couldn't establish interrupt"); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + return; + } + printf(": %s\n", intrstr); + + if (rootvp == NULL) + mountroothook_establish(txp_attachhook, sc); + else + txp_attachhook(sc); + } int @@ -354,8 +381,10 @@ txp_download_fw(sc) { struct txp_fw_file_header *fileheader; struct txp_fw_section_header *secthead; - int sect; u_int32_t r, i, ier, imr; + size_t buflen; + int sect, err; + u_char *buf; ier = READ_REG(sc, TXP_IER); WRITE_REG(sc, TXP_IER, ier | TXP_INT_A2H_0); @@ -370,17 +399,24 @@ txp_download_fw(sc) DELAY(50); } if (r != STAT_WAITING_FOR_HOST_REQUEST) { - printf(": not waiting for host request\n"); + printf("not waiting for host request\n"); return (-1); } /* Ack the status */ WRITE_REG(sc, TXP_ISR, TXP_INT_A2H_0); - fileheader = (struct txp_fw_file_header *)tc990image; + err = loadfirmware("3c990", &buf, &buflen); + if (err) { + printf(": failed loadfirmware of file 3c990: errno %d\n", + err); + return (err); + } + + fileheader = (struct txp_fw_file_header *)buf; if (bcmp("TYPHOON", fileheader->magicid, sizeof(fileheader->magicid))) { - printf(": fw invalid magic\n"); - return (-1); + printf("firmware invalid magic\n"); + goto fail; } /* Tell boot firmware to get ready for image */ @@ -388,16 +424,16 @@ txp_download_fw(sc) WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_RUNTIME_IMAGE); if (txp_download_fw_wait(sc)) { - printf("%s: fw wait failed, initial\n", sc->sc_dev.dv_xname); - return (-1); + printf("fw wait failed, initial\n"); + goto fail; } - secthead = (struct txp_fw_section_header *)(((u_int8_t *)tc990image) + + secthead = (struct txp_fw_section_header *)(buf + sizeof(struct txp_fw_file_header)); for (sect = 0; sect < letoh32(fileheader->nsections); sect++) { - if (txp_download_fw_section(sc, secthead, sect)) - return (-1); + if (txp_download_fw_section(sc, secthead, sect, buf, buflen)) + goto fail; secthead = (struct txp_fw_section_header *) (((u_int8_t *)secthead) + letoh32(secthead->nbytes) + sizeof(*secthead)); @@ -412,14 +448,19 @@ txp_download_fw(sc) DELAY(50); } if (r != STAT_WAITING_FOR_BOOT) { - printf(": not waiting for boot\n"); - return (-1); + printf("not waiting for boot\n"); + goto fail; } WRITE_REG(sc, TXP_IER, ier); WRITE_REG(sc, TXP_IMR, imr); + free(buf, M_DEVBUF); + printf("loaded firmware, "); return (0); +fail: + free(buf, M_DEVBUF); + return (-1); } int @@ -436,7 +477,7 @@ txp_download_fw_wait(sc) } if (!(r & TXP_INT_A2H_0)) { - printf(": fw wait failed comm0\n"); + printf("fw wait failed comm0\n"); return (-1); } @@ -444,17 +485,19 @@ txp_download_fw_wait(sc) r = READ_REG(sc, TXP_A2H_0); if (r != STAT_WAITING_FOR_SEGMENT) { - printf(": fw not waiting for segment\n"); + printf("fw not waiting for segment\n"); return (-1); } return (0); } int -txp_download_fw_section(sc, sect, sectnum) +txp_download_fw_section(sc, sect, sectnum, buf, buflen) struct txp_softc *sc; struct txp_fw_section_header *sect; int sectnum; + u_char *buf; + size_t buflen; { struct txp_dma_alloc dma; int rseg, err = 0; @@ -466,22 +509,22 @@ txp_download_fw_section(sc, sect, sectnum) return (0); /* Make sure we aren't past the end of the image */ - rseg = ((u_int8_t *)sect) - ((u_int8_t *)tc990image); - if (rseg >= sizeof(tc990image)) { - printf(": fw invalid section address, section %d\n", sectnum); + rseg = ((u_int8_t *)sect) - ((u_int8_t *)buf); + if (rseg >= buflen) { + printf("fw invalid section address, section %d\n", sectnum); return (-1); } /* Make sure this section doesn't go past the end */ rseg += letoh32(sect->nbytes); - if (rseg >= sizeof(tc990image)) { - printf(": fw truncated section %d\n", sectnum); + if (rseg >= buflen) { + printf("fw truncated section %d\n", sectnum); return (-1); } /* map a buffer, copy segment to it, get physaddr */ if (txp_dma_malloc(sc, letoh32(sect->nbytes), &dma, 0)) { - printf(": fw dma malloc failed, section %d\n", sectnum); + printf("fw dma malloc failed, section %d\n", sectnum); return (-1); } @@ -498,7 +541,7 @@ txp_download_fw_section(sc, sect, sectnum) m.m_flags = 0; csum = in_cksum(&m, letoh32(sect->nbytes)); if (csum != sect->cksum) { - printf(": fw section %d, bad cksum (expected 0x%x got 0x%x)\n", + printf("fw section %d, bad cksum (expected 0x%x got 0x%x)\n", sectnum, sect->cksum, csum); err = -1; goto bail; @@ -877,7 +920,7 @@ txp_alloc_rings(sc) /* boot record */ if (txp_dma_malloc(sc, sizeof(struct txp_boot_record), &sc->sc_boot_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate boot record\n"); + printf("can't allocate boot record\n"); return (-1); } boot = (struct txp_boot_record *)sc->sc_boot_dma.dma_vaddr; @@ -887,7 +930,7 @@ txp_alloc_rings(sc) /* host variables */ if (txp_dma_malloc(sc, sizeof(struct txp_hostvar), &sc->sc_host_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate host ring\n"); + printf("can't allocate host ring\n"); goto bail_boot; } bzero(sc->sc_host_dma.dma_vaddr, sizeof(struct txp_hostvar)); @@ -898,7 +941,7 @@ txp_alloc_rings(sc) /* high priority tx ring */ if (txp_dma_malloc(sc, sizeof(struct txp_tx_desc) * TX_ENTRIES, &sc->sc_txhiring_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate high tx ring\n"); + printf("can't allocate high tx ring\n"); goto bail_host; } bzero(sc->sc_txhiring_dma.dma_vaddr, sizeof(struct txp_tx_desc) * TX_ENTRIES); @@ -925,7 +968,7 @@ txp_alloc_rings(sc) /* low priority tx ring */ if (txp_dma_malloc(sc, sizeof(struct txp_tx_desc) * TX_ENTRIES, &sc->sc_txloring_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate low tx ring\n"); + printf("can't allocate low tx ring\n"); goto bail_txhiring; } bzero(sc->sc_txloring_dma.dma_vaddr, sizeof(struct txp_tx_desc) * TX_ENTRIES); @@ -940,7 +983,7 @@ txp_alloc_rings(sc) /* high priority rx ring */ if (txp_dma_malloc(sc, sizeof(struct txp_rx_desc) * RX_ENTRIES, &sc->sc_rxhiring_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate high rx ring\n"); + printf("can't allocate high rx ring\n"); goto bail_txloring; } bzero(sc->sc_rxhiring_dma.dma_vaddr, sizeof(struct txp_rx_desc) * RX_ENTRIES); @@ -957,7 +1000,7 @@ txp_alloc_rings(sc) /* low priority ring */ if (txp_dma_malloc(sc, sizeof(struct txp_rx_desc) * RX_ENTRIES, &sc->sc_rxloring_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate low rx ring\n"); + printf("can't allocate low rx ring\n"); goto bail_rxhiring; } bzero(sc->sc_rxloring_dma.dma_vaddr, sizeof(struct txp_rx_desc) * RX_ENTRIES); @@ -974,7 +1017,7 @@ txp_alloc_rings(sc) /* command ring */ if (txp_dma_malloc(sc, sizeof(struct txp_cmd_desc) * CMD_ENTRIES, &sc->sc_cmdring_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate command ring\n"); + printf("can't allocate command ring\n"); goto bail_rxloring; } bzero(sc->sc_cmdring_dma.dma_vaddr, sizeof(struct txp_cmd_desc) * CMD_ENTRIES); @@ -988,7 +1031,7 @@ txp_alloc_rings(sc) /* response ring */ if (txp_dma_malloc(sc, sizeof(struct txp_rsp_desc) * RSP_ENTRIES, &sc->sc_rspring_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate response ring\n"); + printf("can't allocate response ring\n"); goto bail_cmdring; } bzero(sc->sc_rspring_dma.dma_vaddr, sizeof(struct txp_rsp_desc) * RSP_ENTRIES); @@ -1002,7 +1045,7 @@ txp_alloc_rings(sc) /* receive buffer ring */ if (txp_dma_malloc(sc, sizeof(struct txp_rxbuf_desc) * RXBUF_ENTRIES, &sc->sc_rxbufring_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate rx buffer ring\n"); + printf("can't allocate rx buffer ring\n"); goto bail_rspring; } bzero(sc->sc_rxbufring_dma.dma_vaddr, sizeof(struct txp_rxbuf_desc) * RXBUF_ENTRIES); @@ -1056,7 +1099,7 @@ txp_alloc_rings(sc) /* zero dma */ if (txp_dma_malloc(sc, sizeof(u_int32_t), &sc->sc_zero_dma, BUS_DMA_COHERENT)) { - printf(": can't allocate response ring\n"); + printf("can't allocate response ring\n"); goto bail_rxbufring; } bzero(sc->sc_zero_dma.dma_vaddr, sizeof(u_int32_t)); @@ -1071,7 +1114,7 @@ txp_alloc_rings(sc) DELAY(50); } if (r != STAT_WAITING_FOR_BOOT) { - printf(": not waiting for boot\n"); + printf("not waiting for boot\n"); goto bail; } WRITE_REG(sc, TXP_H2A_2, sc->sc_boot_dma.dma_paddr >> 32); @@ -1086,7 +1129,7 @@ txp_alloc_rings(sc) DELAY(50); } if (r != STAT_RUNNING) { - printf(": fw not running\n"); + printf("fw not running\n"); goto bail; } |