summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorUlf Carlsson <md1ulfc@mdstud.chalmers.se>2000-06-06 07:43:12 +0000
committerUlf Carlsson <md1ulfc@mdstud.chalmers.se>2000-06-06 07:43:12 +0000
commit9fb403ee99d7c6b74459b888315929f47e31b013 (patch)
treee30bd5470d4b19707ac8721a18f8410b3280deb8 /drivers
parent0f82b072092fd4ce23e6addeac36b7a243c6cc4a (diff)
The Search ROM functionality should be used when we locate the NIC
since there are two iButton memories when we have the IOC3 on a PCI card. We only use the DS1981U and leave the DS1990A alone. Try this Ralf..
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ioc3-eth.c148
1 files changed, 117 insertions, 31 deletions
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index dd6552af0..396dce5e5 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -178,6 +178,30 @@ nic_reset(struct ioc3 *ioc3)
return presence;
}
+static inline int
+nic_read_bit(struct ioc3 *ioc3)
+{
+ int result;
+
+ ioc3_w(mcr, mcr_pack(6, 13));
+ result = nic_wait(ioc3);
+ ioc3_w(mcr, mcr_pack(0, 100));
+ nic_wait(ioc3);
+
+ return result;
+}
+
+static inline void
+nic_write_bit(struct ioc3 *ioc3, int bit)
+{
+ if (bit)
+ ioc3_w(mcr, mcr_pack(6, 110));
+ else
+ ioc3_w(mcr, mcr_pack(80, 30));
+
+ nic_wait(ioc3);
+}
+
/*
* Read a byte from an iButton device
*/
@@ -187,13 +211,8 @@ nic_read_byte(struct ioc3 *ioc3)
u32 result = 0;
int i;
- for (i = 0; i < 8; i++) {
- ioc3_w(mcr, mcr_pack(6, 13));
- result = (result >> 1) | (nic_wait(ioc3) << 7);
-
- ioc3_w(mcr, mcr_pack(0, 100));
- nic_wait(ioc3);
- }
+ for (i = 0; i < 8; i++)
+ result = (result >> 1) | (nic_read_bit(ioc3) << 7);
return result;
}
@@ -210,34 +229,103 @@ nic_write_byte(struct ioc3 *ioc3, int byte)
bit = byte & 1;
byte >>= 1;
- if (bit)
- ioc3_w(mcr, mcr_pack(6, 110));
- else
- ioc3_w(mcr, mcr_pack(80, 30));
- nic_wait(ioc3);
+ nic_write_bit(ioc3, bit);
}
}
-static void nic_show_regnr(struct ioc3 *ioc3)
+static u64
+nic_find(struct ioc3 *ioc3, int *last)
{
- const char *type;
- u8 regnr[8];
- int i;
+ int a, b, index, disc;
+ u64 address = 0;
- nic_write_byte(ioc3, 0x33);
- for (i = 0; i < 8; i++)
- regnr[i] = nic_read_byte(ioc3);
+ nic_reset(ioc3);
+ /* Search ROM. */
+ nic_write_byte(ioc3, 0xf0);
- switch (regnr[0]) {
- case 0x01: type = "DS1990A"; break;
- case 0x91: type = "DS1981U"; break;
- default: type = "unknown"; break;
+ /* Algorithm from ``Book of iButton Standards''. */
+ for (index = 0, disc = 0; index < 64; index++) {
+ a = nic_read_bit(ioc3);
+ b = nic_read_bit(ioc3);
+
+ if (a && b) {
+ printk("NIC search failed.\n");
+ *last = 0;
+ return 0;
+ }
+
+ if (!a && !b) {
+ if (index == *last) {
+ address |= 1UL << index;
+ } else if (index > *last) {
+ address &= ~(1UL << index);
+ disc = index;
+ } else if ((address & (1UL << index)) == 0)
+ disc = index;
+ nic_write_bit(ioc3, address & (1UL << index));
+ continue;
+ } else {
+ if (a)
+ address |= 1UL << index;
+ else
+ address &= ~(1UL << index);
+ nic_write_bit(ioc3, a);
+ continue;
+ }
}
- printk("Found %s NIC, registration number "
- "%02x:%02x:%02x:%02x:%02x:%02x, CRC %02x.\n", type,
- regnr[1], regnr[2], regnr[3], regnr[4], regnr[5], regnr[6],
- regnr[7]);
+ *last = disc;
+
+ return address;
+}
+
+static void nic_init(struct ioc3 *ioc3)
+{
+ const char *type;
+ u8 crc;
+ u8 serial[6];
+ int save = 0, i;
+
+ type = "unknown";
+
+ do {
+ u64 reg;
+ reg = nic_find(ioc3, &save);
+
+ switch (reg & 0xff) {
+ case 0x91:
+ type = "DS1981U";
+ break;
+ default:
+ if (save == 0) {
+ printk("No NIC connected.\n");
+ return;
+ }
+ continue;
+ }
+
+ nic_reset(ioc3);
+
+ /* Match ROM. */
+ nic_write_byte(ioc3, 0x55);
+ for (i = 0; i < 8; i++)
+ nic_write_byte(ioc3, (reg >> (i << 3)) & 0xff);
+
+ reg >>= 8; /* Shift out type. */
+ for (i = 0; i < 6; i++) {
+ serial[i] = reg & 0xff;
+ reg >>= 8;
+ }
+ crc = reg & 0xff;
+ } while (0);
+
+ printk("Found %s NIC", type);
+ if (type != "unknown") {
+ printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x,"
+ " CRC %02x", serial[0], serial[1], serial[2],
+ serial[3], serial[4], serial[5], crc);
+ }
+ printk(".\n");
}
/*
@@ -250,11 +338,9 @@ static void ioc3_get_eaddr(struct net_device *dev, struct ioc3 *ioc3)
ioc3_w(gpcr_s, (1 << 21));
- nic_reset(ioc3);
- nic_show_regnr(ioc3);
+ nic_init(ioc3);
- nic_reset(ioc3);
- nic_write_byte(ioc3, 0xcc);
+ /* Read Memory. */
nic_write_byte(ioc3, 0xf0);
nic_write_byte(ioc3, 0x00);
nic_write_byte(ioc3, 0x00);