summaryrefslogtreecommitdiffstats
path: root/sys/pc98
diff options
context:
space:
mode:
authorkato <kato@FreeBSD.org>1997-08-21 08:34:47 +0000
committerkato <kato@FreeBSD.org>1997-08-21 08:34:47 +0000
commit95c812f7d496c1371480f79055d2600186581a8d (patch)
tree9fff5984396e62fdc043df228b6c49e5573ba1e6 /sys/pc98
parent3a47df38a22c563d57ae36f6878ab164d0de81b6 (diff)
downloadFreeBSD-src-95c812f7d496c1371480f79055d2600186581a8d.zip
FreeBSD-src-95c812f7d496c1371480f79055d2600186581a8d.tar.gz
3c509.c was identical to kzipboot/unzip.c. I just copied it from
i386/boot/netboot/3c509.c. PC-98 support will be added near future. Submitted by: Tor Egge <Tor.Egge@idi.ntnu.no>
Diffstat (limited to 'sys/pc98')
-rw-r--r--sys/pc98/boot/netboot/3c509.c699
1 files changed, 573 insertions, 126 deletions
diff --git a/sys/pc98/boot/netboot/3c509.c b/sys/pc98/boot/netboot/3c509.c
index 93a2c8b..adf721c 100644
--- a/sys/pc98/boot/netboot/3c509.c
+++ b/sys/pc98/boot/netboot/3c509.c
@@ -1,155 +1,602 @@
-/*
- * unzip.c -- decompress files in gzip or pkzip format.
- * Copyright (C) 1992-1993 Jean-loup Gailly
- *
- * Adapted for Linux booting by Hannu Savolainen 1993
- * Adapted for FreeBSD booting by Serge Vakulenko
- *
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- *
- * The code in this file is derived from the file funzip.c written
- * and put in the public domain by Mark Adler.
- */
+/**************************************************************************
+NETBOOT - BOOTP/TFTP Bootstrap Program
-/*
- * This version can extract files in gzip or pkzip format.
- * For the latter, only the first entry is extracted, and it has to be
- * either deflated or stored.
- */
+Author: Martin Renters.
+ Date: Mar 22 1995
-#include "gzip.h"
-
-#include <sys/types.h>
-#include <sys/inflate.h>
-
-/* PKZIP header definitions */
-#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */
-#define LOCFLG 6 /* offset of bit flag */
-#define CRPFLG 1 /* bit for encrypted entry */
-#define EXTFLG 8 /* bit for extended local header */
-#define LOCHOW 8 /* offset of compression method */
-#define LOCTIM 10 /* file mod time (for decryption) */
-#define LOCCRC 14 /* offset of crc */
-#define LOCSIZ 18 /* offset of compressed size */
-#define LOCLEN 22 /* offset of uncompressed length */
-#define LOCFIL 26 /* offset of file name field length */
-#define LOCEXT 28 /* offset of extra field length */
-#define LOCHDR 30 /* size of local header, including sig */
-#define EXTHDR 16 /* size of extended local header, inc sig */
-
-int pkzip; /* set for a pkzip file */
-int extended; /* set if extended local header */
-
-/* Macros for getting two-byte and four-byte header values */
-#define SH(p) ((ushort)(uchar)((p)[0]) | ((ushort)(uchar)((p)[1]) << 8))
-#define LG(p) ((ulong)(SH(p)) | ((ulong)(SH((p)+2)) << 16))
+ This code is based heavily on David Greenman's if_ed.c driver and
+ Andres Vega Garcia's if_ep.c driver.
-/*
- * Check zip file and advance inptr to the start of the compressed data.
- * Get ofname from the local header if necessary.
- */
-void check_zipfile()
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ Copyright (C) 1993-1995, Andres Vega Garcia.
+ Copyright (C) 1995, Serge Babkin.
+ This software may be used, modified, copied, distributed, and sold, in
+ both source and binary form provided that the above copyright and these
+ terms are retained. Under no circumstances are the authors responsible for
+ the proper functioning of this software, nor do the authors assume any
+ responsibility for damages incurred with its use.
+
+3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
+
+$Id$
+
+***************************************************************************/
+
+/* #define EDEBUG */
+
+#include "netboot.h"
+#include "3c509.h"
+
+short aui;
+char bnc=0, utp=0; /* for 3C509 */
+unsigned short eth_nic_base;
+unsigned short eth_asic_base;
+unsigned short eth_base;
+unsigned char eth_tx_start;
+unsigned char eth_laar;
+unsigned char eth_flags;
+unsigned char eth_vendor;
+unsigned char eth_memsize;
+unsigned char *eth_bmem;
+unsigned char *eth_rmem;
+unsigned char *eth_node_addr;
+
+static send_ID_sequence();
+static get_eeprom_data();
+static get_e();
+
+/**************************************************************************
+The following two variables are used externally
+***************************************************************************/
+char packet[ETHER_MAX_LEN];
+int packetlen;
+
+/*********************** Name of driver *********************************/
+
+char eth_driver[]="ep0";
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+eth_probe()
+{
+ /* common variables */
+ int i;
+ /* variables for 3C509 */
+ int data, j, io_base, id_port = EP_ID_PORT;
+ int nisa = 0, neisa = 0;
+ u_short k;
+ int ep_current_tag = EP_LAST_TAG + 1;
+ short *p;
+
+ eth_vendor = VENDOR_NONE;
+
+ /*********************************************************
+ Search for 3Com 509 card
+ ***********************************************************/
+
+ /* Look for the EISA boards, leave them activated */
+ /* search for the first card, ignore all others */
+ for(j = 1; j < 16 && eth_vendor==VENDOR_NONE ; j++) {
+ io_base = (j * EP_EISA_START) | EP_EISA_W0;
+ if (inw(io_base + EP_W0_MFG_ID) != MFG_ID)
+ continue;
+
+ /* we must found 0x1f if the board is EISA configurated */
+ if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
+ continue;
+
+ /* Reset and Enable the card */
+ outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
+ DELAY(1000); /* we must wait at least 1 ms */
+ outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
+
+ /*
+ * Once activated, all the registers are mapped in the range
+ * x000 - x00F, where x is the slot number.
+ */
+ eth_base = j * EP_EISA_START;
+ eth_vendor = VENDOR_3C509;
+ }
+ ep_current_tag--;
+
+ /* Look for the ISA boards. Init and leave them actived */
+ /* search for the first card, ignore all others */
+ outb(id_port, 0xc0); /* Global reset */
+ DELAY(1000);
+ for (i = 0; i < EP_MAX_BOARDS && eth_vendor==VENDOR_NONE; i++) {
+ outb(id_port, 0);
+ outb(id_port, 0);
+ send_ID_sequence(id_port);
+
+ data = get_eeprom_data(id_port, EEPROM_MFG_ID);
+ if (data != MFG_ID)
+ break;
+
+ /* resolve contention using the Ethernet address */
+ for (j = 0; j < 3; j++)
+ data = get_eeprom_data(id_port, j);
+
+ eth_base =
+ (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
+ outb(id_port, ep_current_tag); /* tags board */
+ outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
+ eth_vendor = VENDOR_3C509;
+ ep_current_tag--;
+ }
+
+ if(eth_vendor != VENDOR_3C509)
+ goto no3c509;
+
+ /*
+ * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
+ * 0x9[0-f]50
+ */
+ GO_WINDOW(0);
+ k = get_e(EEPROM_PROD_ID);
+ if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
+ goto no3c509;
+
+ if(eth_base >= EP_EISA_START) {
+ printf("3C5x9 board on EISA at 0x%x - ",eth_base);
+ } else {
+ printf("3C5x9 board on ISA at 0x%x - ",eth_base);
+ }
+
+ /* test for presence of connectors */
+ i = inw(IS_BASE + EP_W0_CONFIG_CTRL);
+ j = inw(IS_BASE + EP_W0_ADDRESS_CFG) >> 14;
+
+ switch(j) {
+ case 0:
+ if(i & IS_UTP) {
+ printf("10baseT\r\n");
+ utp=1;
+ }
+ else {
+ printf("10baseT not present\r\n");
+ eth_vendor=VENDOR_NONE;
+ goto no3c509;
+ }
+
+ break;
+ case 1:
+ if(i & IS_AUI)
+ printf("10base5\r\n");
+ else {
+ printf("10base5 not present\r\n");
+ eth_vendor=VENDOR_NONE;
+ goto no3c509;
+ }
+
+ break;
+ case 3:
+ if(i & IS_BNC) {
+ printf("10base2\r\n");
+ bnc=1;
+ }
+ else {
+ printf("10base2 not present\r\n");
+ eth_vendor=VENDOR_NONE;
+ goto no3c509;
+ }
+
+ break;
+ default:
+ printf("unknown connector\r\n");
+ eth_vendor=VENDOR_NONE;
+ goto no3c509;
+ }
+ /*
+ * Read the station address from the eeprom
+ */
+ p = (u_short *) arptable[ARP_CLIENT].node;
+ for (i = 0; i < 3; i++) {
+ GO_WINDOW(0);
+ p[i] = htons(get_e(i));
+ GO_WINDOW(2);
+ outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
+ }
+
+ printf("Ethernet address: ");
+ for(i=0; i<5; i++) {
+ printf("%b:",arptable[ARP_CLIENT].node[i]);
+ }
+ printf("%b\n",arptable[ARP_CLIENT].node[i]);
+
+ eth_node_addr = arptable[ARP_CLIENT].node;
+ eth_reset();
+ return eth_vendor;
+no3c509:
+ eth_vendor = VENDOR_NONE;
+
+ return VENDOR_NONE;
+}
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+eth_reset()
{
- uchar *h = inbuf + inptr; /* first local header */
+ int s, i;
+
+ /***********************************************************
+ Reset 3Com 509 card
+ *************************************************************/
+
+ if(eth_vendor != VENDOR_3C509)
+ goto no3c509;
- /* Check validity of local header, and skip name and extra fields */
- inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
+ /* stop card */
+ outw(BASE + EP_COMMAND, RX_DISABLE);
+ outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
+ while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
+ outw(BASE + EP_COMMAND, TX_DISABLE);
+ outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
+ outw(BASE + EP_COMMAND, RX_RESET);
+ outw(BASE + EP_COMMAND, TX_RESET);
+ outw(BASE + EP_COMMAND, C_INTR_LATCH);
+ outw(BASE + EP_COMMAND, SET_RD_0_MASK);
+ outw(BASE + EP_COMMAND, SET_INTR_MASK);
+ outw(BASE + EP_COMMAND, SET_RX_FILTER);
- if (inptr > insize || LG(h) != LOCSIG)
- error("input not a zip");
+ /*
+ /* initialize card
+ */
+ while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
- method = h[LOCHOW];
- if (method != STORED && method != DEFLATED)
- error("first entry not deflated or stored--can't extract");
+ GO_WINDOW(0);
- /* If entry encrypted, decrypt and validate encryption header */
- if (h[LOCFLG] & CRPFLG)
- error("encrypted file");
+ /* Disable the card */
+ outw(BASE + EP_W0_CONFIG_CTRL, 0);
+
+ /* Configure IRQ to none */
+ outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(0));
+
+ /* Enable the card */
+ outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
+
+ GO_WINDOW(2);
+
+ /* Reload the ether_addr. */
+ for (i = 0; i < 6; i++)
+ outb(BASE + EP_W2_ADDR_0 + i, arptable[ARP_CLIENT].node[i]);
+
+ outw(BASE + EP_COMMAND, RX_RESET);
+ outw(BASE + EP_COMMAND, TX_RESET);
+
+ /* Window 1 is operating window */
+ GO_WINDOW(1);
+ for (i = 0; i < 31; i++)
+ inb(BASE + EP_W1_TX_STATUS);
+
+ /* get rid of stray intr's */
+ outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
+
+ outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);
+
+ outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
+
+ outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
+ FIL_BRDCST);
+
+ /* configure BNC */
+ if(bnc) {
+ outw(BASE + EP_COMMAND, START_TRANSCEIVER);
+ DELAY(1000);
+ }
+ /* configure UTP */
+ if(utp) {
+ GO_WINDOW(4);
+ outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
+ GO_WINDOW(1);
+ }
+
+ /* start tranciever and receiver */
+ outw(BASE + EP_COMMAND, RX_ENABLE);
+ outw(BASE + EP_COMMAND, TX_ENABLE);
+
+ /* set early threshold for minimal packet length */
+ outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | 64);
+
+ outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);
+
+ return 1;
+no3c509:
- /* Save flags for unzip() */
- extended = (h[LOCFLG] & EXTFLG) != 0;
- pkzip = 1;
}
-int
-Flush (void *nu, u_char *buf, u_long cnt)
+/**************************************************************************
+ETH_TRANSMIT - Transmit a frame
+***************************************************************************/
+static const char padmap[] = {
+ 0, 3, 2, 1};
+
+eth_transmit(d,t,s,p)
+char *d; /* Destination */
+unsigned short t; /* Type */
+unsigned short s; /* size */
+char *p; /* Packet */
{
- outcnt = cnt;
- flush_window();
+ register u_int len;
+ int pad;
+ int status;
+ unsigned char c;
+
+ if(eth_vendor != VENDOR_3C509)
+ goto no3c509;
+
+#ifdef EDEBUG
+ printf("{l=%d,t=%x}",s+14,t);
+#endif
+
+ /* swap bytes of type */
+ t=(( t&0xFF )<<8) | ((t>>8) & 0xFF);
+
+ len=s+14; /* actual length of packet */
+ pad = padmap[len & 3];
+
+ /*
+ * The 3c509 automatically pads short packets to minimum ethernet length,
+ * but we drop packets that are too large. Perhaps we should truncate
+ * them instead?
+ */
+ if (len + pad > ETHER_MAX_LEN) {
+ return 0;
+ }
+
+ /* drop acknowledgements */
+ while(( status=inb(BASE + EP_W1_TX_STATUS) )& TXS_COMPLETE ) {
+ if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
+ outw(BASE + EP_COMMAND, TX_RESET);
+ outw(BASE + EP_COMMAND, TX_ENABLE);
+ }
+
+ outb(BASE + EP_W1_TX_STATUS, 0x0);
+ }
+
+ while (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
+ /* no room in FIFO */
+ }
+
+ outw(BASE + EP_W1_TX_PIO_WR_1, len);
+ outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */
+
+ /* write packet */
+ outsw(BASE + EP_W1_TX_PIO_WR_1, d, 3);
+ outsw(BASE + EP_W1_TX_PIO_WR_1, eth_node_addr, 3);
+ outw(BASE + EP_W1_TX_PIO_WR_1, t);
+ outsw(BASE + EP_W1_TX_PIO_WR_1, p, s / 2);
+ if (s & 1)
+ outb(BASE + EP_W1_TX_PIO_WR_1, *(p+s - 1));
+
+ while (pad--)
+ outb(BASE + EP_W1_TX_PIO_WR_1, 0); /* Padding */
+
+ /* timeout after sending */
+ DELAY(1000);
return 0;
+no3c509:
}
-int
-NextByte (void *nu)
+/**************************************************************************
+ETH_POLL - Wait for a frame
+***************************************************************************/
+eth_poll()
{
- return ((int) get_byte ());
+ /* common variables */
+ unsigned short type = 0;
+ unsigned short len;
+ /* variables for 3C509 */
+ struct ether_header *eh;
+ int lenthisone;
+ short rx_fifo2, status, cst;
+ register short rx_fifo;
+
+ if(eth_vendor!=VENDOR_3C509)
+ goto no3c509;
+
+ cst=inw(BASE + EP_STATUS);
+
+#ifdef EDEBUG
+ if(cst & 0x1FFF)
+ printf("-%x-",cst);
+#endif
+
+ if( (cst & (S_RX_COMPLETE|S_RX_EARLY) )==0 ) {
+ /* acknowledge everything */
+ outw(BASE + EP_COMMAND, ACK_INTR| (cst & S_5_INTS));
+ outw(BASE + EP_COMMAND, C_INTR_LATCH);
+
+ return 0;
+ }
+
+ status = inw(BASE + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%x*",status);
+#endif
+
+ if (status & ERR_RX) {
+ outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
+ return 0;
+ }
+
+ rx_fifo = status & RX_BYTES_MASK;
+ if (rx_fifo==0)
+ return 0;
+
+ /* read packet */
+#ifdef EDEBUG
+ printf("[l=%d",rx_fifo);
+#endif
+ insw(BASE + EP_W1_RX_PIO_RD_1, packet, rx_fifo / 2);
+ if(rx_fifo & 1)
+ packet[rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1);
+ packetlen=rx_fifo;
+
+ while(1) {
+ status = inw(BASE + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+ printf("*%x*",status);
+#endif
+ rx_fifo = status & RX_BYTES_MASK;
+
+ if(rx_fifo>0) {
+ insw(BASE + EP_W1_RX_PIO_RD_1, packet+packetlen, rx_fifo / 2);
+ if(rx_fifo & 1)
+ packet[packetlen+rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1);
+ packetlen+=rx_fifo;
+#ifdef EDEBUG
+ printf("+%d",rx_fifo);
+#endif
+ }
+
+ if(( status & RX_INCOMPLETE )==0) {
+#ifdef EDEBUG
+ printf("=%d",packetlen);
+#endif
+ break;
+ }
+
+ DELAY(1000);
+ }
+
+ /* acknowledge reception of packet */
+ outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
+ while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
+
+ type = (packet[12]<<8) | packet[13];
+
+#ifdef EDEBUG
+ if(packet[0]+packet[1]+packet[2]+packet[3]+packet[4]+
+ packet[5] == 0xFF*6)
+ printf(",t=0x%x,b]",type);
+ else
+ printf(",t=0x%x]",type);
+#endif
+
+
+ if (type == ARP) {
+ struct arprequest *arpreq;
+ unsigned long reqip;
+
+ arpreq = (struct arprequest *)&packet[ETHER_HDR_LEN];
+
+#ifdef EDEBUG
+ printf("(ARP %I->%I)",ntohl(*(int*)arpreq->sipaddr),
+ ntohl(*(int*)arpreq->tipaddr));
+#endif
+
+ convert_ipaddr(&reqip, arpreq->tipaddr);
+ if ((ntohs(arpreq->opcode) == ARP_REQUEST) &&
+ (reqip == arptable[ARP_CLIENT].ipaddr)) {
+ arpreq->opcode = htons(ARP_REPLY);
+ bcopy(arpreq->sipaddr, arpreq->tipaddr, 4);
+ bcopy(arpreq->shwaddr, arpreq->thwaddr, 6);
+ bcopy(arptable[ARP_CLIENT].node, arpreq->shwaddr, 6);
+ convert_ipaddr(arpreq->sipaddr, &reqip);
+ eth_transmit(arpreq->thwaddr, ARP, sizeof(struct arprequest),
+ arpreq);
+ return(0);
+ }
+ } else if(type==IP) {
+ struct iphdr *iph;
+
+ iph = (struct iphdr *)&packet[ETHER_HDR_LEN];
+#ifdef EDEBUG
+ printf("(IP %I-%d->%I)",ntohl(*(int*)iph->src),
+ ntohs(iph->protocol),ntohl(*(int*)iph->dest));
+#endif
+ }
+
+ return 1;
+
+no3c509:
}
-struct inflate infl; /* put it into the BSS */
+
+/*************************************************************************
+ 3Com 509 - specific routines
+**************************************************************************/
+
+static int
+eeprom_rdy()
+{
+ int i;
+
+ for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
+ if (i >= MAX_EEPROMBUSY) {
+ printf("3c509: eeprom failed to come ready.\r\n");
+ return (0);
+ }
+ return (1);
+}
/*
- * Unzip in to out. This routine works on both gzip and pkzip files.
- *
- * IN assertions: the buffer inbuf contains already the beginning of
- * the compressed data, from offsets inptr to insize-1 included.
- * The magic header has already been checked. The output buffer is cleared.
+ * get_e: gets a 16 bits word from the EEPROM. we must have set the window
+ * before
*/
-
-void unzip()
+static int
+get_e(offset)
+int offset;
{
- ulong orig_crc = 0; /* original crc */
- ulong orig_len = 0; /* original uncompressed length */
- uchar buf[EXTHDR]; /* extended local header */
- int n, res;
+ if (!eeprom_rdy())
+ return (0xffff);
+ outw(IS_BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset);
+ if (!eeprom_rdy())
+ return (0xffff);
+ return (inw(IS_BASE + EP_W0_EEPROM_DATA));
+}
- crc = 0xffffffffL; /* initialize crc */
+static int
+send_ID_sequence(port)
+int port;
+{
+ int cx, al;
- if (pkzip && !extended) { /* crc and length at the end otherwise */
- orig_crc = LG(inbuf + LOCCRC);
- orig_len = LG(inbuf + LOCLEN);
+ for (al = 0xff, cx = 0; cx < 255; cx++) {
+ outb(port, al);
+ al <<= 1;
+ if (al & 0x100)
+ al ^= 0xcf;
}
+ return (1);
+}
- if (method != DEFLATED)
- error("internal error, invalid method");
- infl.gz_input = NextByte;
- infl.gz_output = Flush;
- infl.gz_slide = window;
- res = inflate (&infl);
- if (res == 3)
- error("out of memory");
- else if (res != 0)
- error("invalid compressed format");
-
- /* Get the crc and original length */
- if (!pkzip) {
- /* crc32 (see algorithm.doc)
- * uncompressed input size modulo 2^32
- */
- for (n = 0; n < 8; n++)
- buf[n] = get_byte(); /* may cause an error if EOF */
- orig_crc = LG(buf);
- orig_len = LG(buf+4);
-
- } else if (extended) { /* If extended header, check it */
- /* signature - 4bytes: 0x50 0x4b 0x07 0x08
- * CRC-32 value
- * compressed size 4-bytes
- * uncompressed size 4-bytes
- */
- for (n = 0; n < EXTHDR; n++)
- buf[n] = get_byte(); /* may cause an error if EOF */
- orig_crc = LG(buf+4);
- orig_len = LG(buf+12);
- }
- /* Validate decompression */
- if (orig_crc != (crc ^ 0xffffffffL))
- error("crc error");
- if (orig_len != output_ptr)
- error("length error");
+/*
+ * We get eeprom data from the id_port given an offset into the eeprom.
+ * Basically; after the ID_sequence is sent to all of the cards; they enter
+ * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
+ * the eeprom data. We then read the port 16 times and with every read; the
+ * cards check for contention (ie: if one card writes a 0 bit and another
+ * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
+ * compares the data on the bus; if there is a difference then that card goes
+ * into ID_WAIT state again). In the meantime; one bit of data is returned in
+ * the AX register which is conveniently returned to us by inb(). Hence; we
+ * read 16 times getting one bit of data with each read.
+ */
+static int
+get_eeprom_data(id_port, offset)
+int id_port;
+int offset;
+{
+ int i, data = 0;
+ outb(id_port, 0x80 + offset);
+ DELAY(1000);
+ for (i = 0; i < 16; i++)
+ data = (data << 1) | (inw(id_port) & 1);
+ return (data);
+}
- /* Check if there are more entries in a pkzip file */
- if (pkzip && inptr+4 < insize && LG(inbuf+inptr) == LOCSIG)
- error("zip file has more than one entry");
+/* a surrogate */
+
+DELAY(val)
+{
+ int c;
+
+ for(c=0; c<val; c+=20) {
+ twiddle();
+ }
}
+
OpenPOWER on IntegriCloud