summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx/aic7xxx_93cx6.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/aic7xxx/aic7xxx_93cx6.c')
-rw-r--r--sys/dev/aic7xxx/aic7xxx_93cx6.c165
1 files changed, 133 insertions, 32 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx_93cx6.c b/sys/dev/aic7xxx/aic7xxx_93cx6.c
index c2a216d..18fd5d2 100644
--- a/sys/dev/aic7xxx/aic7xxx_93cx6.c
+++ b/sys/dev/aic7xxx/aic7xxx_93cx6.c
@@ -14,7 +14,7 @@
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#8 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#14 $
*
* $FreeBSD$
*/
@@ -67,9 +67,15 @@
*
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#ifdef __linux__
+#include "aic7xxx_osm.h"
+#include "aic7xxx_inline.h"
+#include "aic7xxx_93cx6.h"
+#else
+#include <dev/aic7xxx/aic7xxx_osm.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aic7xxx_93cx6.h>
+#endif
/*
* Right now, we only have to read the SEEPROM. But we make it easier to
@@ -77,9 +83,13 @@
*/
static struct seeprom_cmd {
uint8_t len;
- uint8_t bits[3];
+ uint8_t bits[9];
} seeprom_read = {3, {1, 1, 0}};
+static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+
/*
* Wait for the SEERDY to go high; about 800 ns.
*/
@@ -90,15 +100,55 @@ static struct seeprom_cmd {
(void)SEEPROM_INB(sd); /* Clear clock */
/*
+ * Send a START condition and the given command
+ */
+static void
+send_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd)
+{
+ uint8_t temp;
+ int i = 0;
+
+ /* Send chip select for one clock cycle. */
+ temp = sd->sd_MS ^ sd->sd_CS;
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+
+ for (i = 0; i < cmd->len; i++) {
+ if (cmd->bits[i] != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if (cmd->bits[i] != 0)
+ temp ^= sd->sd_DO;
+ }
+}
+
+/*
+ * Clear CS put the chip in the reset state, where it can wait for new commands.
+ */
+static void
+reset_seeprom(struct seeprom_descriptor *sd)
+{
+ uint8_t temp;
+
+ temp = sd->sd_MS;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+}
+
+/*
* Read the serial EEPROM and returns 1 if successful and 0 if
* not successful.
*/
int
-read_seeprom(sd, buf, start_addr, count)
- struct seeprom_descriptor *sd;
- uint16_t *buf;
- u_int start_addr;
- u_int count;
+ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
+ u_int start_addr, u_int count)
{
int i = 0;
u_int k = 0;
@@ -110,26 +160,14 @@ read_seeprom(sd, buf, start_addr, count)
* will range from 0 to count-1.
*/
for (k = start_addr; k < count + start_addr; k++) {
- /* Send chip select for one clock cycle. */
- temp = sd->sd_MS ^ sd->sd_CS;
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
-
/*
* Now we're ready to send the read command followed by the
* address of the 16-bit register we want to read.
*/
- for (i = 0; i < seeprom_read.len; i++) {
- if (seeprom_read.bits[i] != 0)
- temp ^= sd->sd_DO;
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- if (seeprom_read.bits[i] != 0)
- temp ^= sd->sd_DO;
- }
+ send_seeprom_cmd(sd, &seeprom_read);
+
/* Send the 6 or 8 bit address (MSB first, LSB last). */
+ temp = sd->sd_MS ^ sd->sd_CS;
for (i = (sd->sd_chip - 1); i >= 0; i--) {
if ((k & (1 << i)) != 0)
temp ^= sd->sd_DO;
@@ -161,13 +199,7 @@ read_seeprom(sd, buf, start_addr, count)
buf[k - start_addr] = v;
/* Reset the chip select for the next command cycle. */
- temp = sd->sd_MS;
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
+ reset_seeprom(sd);
}
#ifdef AHC_DUMP_EEPROM
printf("\nSerial EEPROM:\n\t");
@@ -182,8 +214,77 @@ read_seeprom(sd, buf, start_addr, count)
return (1);
}
+/*
+ * Write the serial EEPROM and return 1 if successful and 0 if
+ * not successful.
+ */
+int
+ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
+ u_int start_addr, u_int count)
+{
+ uint16_t v;
+ uint8_t temp;
+ int i, k;
+
+ /* Place the chip into write-enable mode */
+ send_seeprom_cmd(sd, &seeprom_ewen);
+ reset_seeprom(sd);
+
+ /* Write all requested data out to the seeprom. */
+ temp = sd->sd_MS ^ sd->sd_CS;
+ for (k = start_addr; k < count + start_addr; k++) {
+ /* Send the write command */
+ send_seeprom_cmd(sd, &seeprom_write);
+
+ /* Send the 6 or 8 bit address (MSB first). */
+ for (i = (sd->sd_chip - 1); i >= 0; i--) {
+ if ((k & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if ((k & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ }
+
+ /* Write the 16 bit value, MSB first */
+ v = buf[k - start_addr];
+ for (i = 15; i >= 0; i--) {
+ if ((v & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if ((v & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ }
+
+ /* Wait for the chip to complete the write */
+ temp = sd->sd_MS;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ temp = sd->sd_MS ^ sd->sd_CS;
+ do {
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ } while ((SEEPROM_DATA_INB(sd) & sd->sd_DI) == 0);
+
+ reset_seeprom(sd);
+ }
+
+ /* Put the chip back into write-protect mode */
+ send_seeprom_cmd(sd, &seeprom_ewds);
+ reset_seeprom(sd);
+
+ return (1);
+}
+
int
-verify_cksum(struct seeprom_config *sc)
+ahc_verify_cksum(struct seeprom_config *sc)
{
int i;
int maxaddr;
OpenPOWER on IntegriCloud