📄 sb1000.c
字号:
while (inb(ioaddr[1] + 6) & 0x80) { if (jiffies >= timeout) { printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n", name); return -ETIME; } } timeout = jiffies + Sb1000TimeOutJiffies; while (inb(ioaddr[1] + 6) & 0x40) { if (jiffies >= timeout) { printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n", name); return -ETIME; } } return 0;}/* Card Send Command (to be used during frame rx) */static inline voidsb1000_send_command(const int ioaddr[], const char* name, const unsigned char out[]){ outb(out[2], ioaddr[0] + 1); outb(out[3], ioaddr[0] + 2); outb(out[4], ioaddr[0] + 3); outb(out[5], ioaddr[0] + 4); outb(out[1], ioaddr[0] + 5); outb(out[0], ioaddr[0] + 7); if (sb1000_debug > 3) printk(KERN_DEBUG "%s: sb1000_send_command out: %02x%02x%02x%02x" "%02x%02x\n", name, out[0], out[1], out[2], out[3], out[4], out[5]); return;}/* Card Read Status (to be used during frame rx) */static inline voidsb1000_read_status(const int ioaddr[], unsigned char in[]){ in[1] = inb(ioaddr[0] + 1); in[2] = inb(ioaddr[0] + 2); in[3] = inb(ioaddr[0] + 3); in[4] = inb(ioaddr[0] + 4); in[0] = inb(ioaddr[0] + 5); return;}/* Issue Read Command (to be used during frame rx) */static inline voidsb1000_issue_read_command(const int ioaddr[], const char* name){ const unsigned char Command0[6] = {0x20, 0x00, 0x00, 0x01, 0x00, 0x00}; sb1000_wait_for_ready_clear(ioaddr, name); outb(0xa0, ioaddr[0] + 6); sb1000_send_command(ioaddr, name, Command0); return;}/* * SB1000 commands for open/configuration *//* reset SB1000 card */static inline intsb1000_reset(const int ioaddr[], const char* name){ unsigned char st[7]; int port, status; const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00}; port = ioaddr[1] + 6; outb(0x4, port); inb(port); udelay(1000); outb(0x0, port); inb(port); nicedelay(60000); outb(0x4, port); inb(port); udelay(1000); outb(0x0, port); inb(port); udelay(0); if ((status = card_send_command(ioaddr, name, Command0, st))) return status; if (st[3] != 0xf0) return -EIO; return 0;}/* check SB1000 firmware CRC */static inline intsb1000_check_CRC(const int ioaddr[], const char* name){ unsigned char st[7]; int crc, status; const unsigned char Command0[6] = {0x80, 0x1f, 0x00, 0x00, 0x00, 0x00}; /* check CRC */ if ((status = card_send_command(ioaddr, name, Command0, st))) return status; if (st[1] != st[3] || st[2] != st[4]) return -EIO; crc = st[1] << 8 | st[2]; return 0;}static inline intsb1000_start_get_set_command(const int ioaddr[], const char* name){ unsigned char st[7]; const unsigned char Command0[6] = {0x80, 0x1b, 0x00, 0x00, 0x00, 0x00}; return card_send_command(ioaddr, name, Command0, st);}static inline intsb1000_end_get_set_command(const int ioaddr[], const char* name){ unsigned char st[7]; int status; const unsigned char Command0[6] = {0x80, 0x1b, 0x02, 0x00, 0x00, 0x00}; const unsigned char Command1[6] = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00}; if ((status = card_send_command(ioaddr, name, Command0, st))) return status; return card_send_command(ioaddr, name, Command1, st);}static inline intsb1000_activate(const int ioaddr[], const char* name){ unsigned char st[7]; int status; const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00}; const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00}; nicedelay(50000); if ((status = card_send_command(ioaddr, name, Command0, st))) return status; if ((status = card_send_command(ioaddr, name, Command1, st))) return status; if (st[3] != 0xf1) { if ((status = sb1000_start_get_set_command(ioaddr, name))) return status; return -EIO; } udelay(1000); return sb1000_start_get_set_command(ioaddr, name);}/* get SB1000 firmware version */static inline intsb1000_get_firmware_version(const int ioaddr[], const char* name, unsigned char version[], int do_end){ unsigned char st[7]; int status; const unsigned char Command0[6] = {0x80, 0x23, 0x00, 0x00, 0x00, 0x00}; if ((status = sb1000_start_get_set_command(ioaddr, name))) return status; if ((status = card_send_command(ioaddr, name, Command0, st))) return status; if (st[0] != 0xa3) return -EIO; version[0] = st[1]; version[1] = st[2]; if (do_end) return sb1000_end_get_set_command(ioaddr, name); else return 0;}/* get SB1000 frequency */static inline intsb1000_get_frequency(const int ioaddr[], const char* name, int* frequency){ unsigned char st[7]; int status; const unsigned char Command0[6] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00}; udelay(1000); if ((status = sb1000_start_get_set_command(ioaddr, name))) return status; if ((status = card_send_command(ioaddr, name, Command0, st))) return status; *frequency = ((st[1] << 8 | st[2]) << 8 | st[3]) << 8 | st[4]; return sb1000_end_get_set_command(ioaddr, name);}/* set SB1000 frequency */static inline intsb1000_set_frequency(const int ioaddr[], const char* name, int frequency){ unsigned char st[7]; int status; unsigned char Command0[6] = {0x80, 0x29, 0x00, 0x00, 0x00, 0x00}; const int FrequencyLowerLimit = 57000; const int FrequencyUpperLimit = 804000; if (frequency < FrequencyLowerLimit || frequency > FrequencyUpperLimit) { printk(KERN_ERR "%s: frequency chosen (%d kHz) is not in the range " "[%d,%d] kHz\n", name, frequency, FrequencyLowerLimit, FrequencyUpperLimit); return -EINVAL; } udelay(1000); if ((status = sb1000_start_get_set_command(ioaddr, name))) return status; Command0[5] = frequency & 0xff; frequency >>= 8; Command0[4] = frequency & 0xff; frequency >>= 8; Command0[3] = frequency & 0xff; frequency >>= 8; Command0[2] = frequency & 0xff; return card_send_command(ioaddr, name, Command0, st);}/* get SB1000 PIDs */static inline intsb1000_get_PIDs(const int ioaddr[], const char* name, short PID[]){ unsigned char st[7]; int status; const unsigned char Command0[6] = {0x80, 0x40, 0x00, 0x00, 0x00, 0x00}; const unsigned char Command1[6] = {0x80, 0x41, 0x00, 0x00, 0x00, 0x00}; const unsigned char Command2[6] = {0x80, 0x42, 0x00, 0x00, 0x00, 0x00}; const unsigned char Command3[6] = {0x80, 0x43, 0x00, 0x00, 0x00, 0x00}; udelay(1000); if ((status = sb1000_start_get_set_command(ioaddr, name))) return status; if ((status = card_send_command(ioaddr, name, Command0, st))) return status; PID[0] = st[1] << 8 | st[2]; if ((status = card_send_command(ioaddr, name, Command1, st))) return status; PID[1] = st[1] << 8 | st[2]; if ((status = card_send_command(ioaddr, name, Command2, st))) return status; PID[2] = st[1] << 8 | st[2]; if ((status = card_send_command(ioaddr, name, Command3, st))) return status; PID[3] = st[1] << 8 | st[2]; return sb1000_end_get_set_command(ioaddr, name);}/* set SB1000 PIDs */static inline intsb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[]){ unsigned char st[7]; short p; int status; unsigned char Command0[6] = {0x80, 0x31, 0x00, 0x00, 0x00, 0x00}; unsigned char Command1[6] = {0x80, 0x32, 0x00, 0x00, 0x00, 0x00}; unsigned char Command2[6] = {0x80, 0x33, 0x00, 0x00, 0x00, 0x00}; unsigned char Command3[6] = {0x80, 0x34, 0x00, 0x00, 0x00, 0x00}; const unsigned char Command4[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00}; udelay(1000); if ((status = sb1000_start_get_set_command(ioaddr, name))) return status; p = PID[0]; Command0[3] = p & 0xff; p >>= 8; Command0[2] = p & 0xff; if ((status = card_send_command(ioaddr, name, Command0, st))) return status; p = PID[1]; Command1[3] = p & 0xff; p >>= 8; Command1[2] = p & 0xff; if ((status = card_send_command(ioaddr, name, Command1, st))) return status; p = PID[2]; Command2[3] = p & 0xff; p >>= 8; Command2[2] = p & 0xff; if ((status = card_send_command(ioaddr, name, Command2, st))) return status; p = PID[3]; Command3[3] = p & 0xff; p >>= 8; Command3[2] = p & 0xff; if ((status = card_send_command(ioaddr, name, Command3, st))) return status; if ((status = card_send_command(ioaddr, name, Command4, st))) return status; return sb1000_end_get_set_command(ioaddr, name);}static inline voidsb1000_print_status_buffer(const char* name, unsigned char st[], unsigned char buffer[], int size){ int i, j, k; printk(KERN_DEBUG "%s: status: %02x %02x\n", name, st[0], st[1]); if (buffer[24] == 0x08 && buffer[25] == 0x00 && buffer[26] == 0x45) { printk(KERN_DEBUG "%s: length: %d protocol: %d from: %d.%d.%d.%d:%d " "to %d.%d.%d.%d:%d\n", name, buffer[28] << 8 | buffer[29], buffer[35], buffer[38], buffer[39], buffer[40], buffer[41], buffer[46] << 8 | buffer[47], buffer[42], buffer[43], buffer[44], buffer[45], buffer[48] << 8 | buffer[49]); } else { for (i = 0, k = 0; i < (size + 7) / 8; i++) { printk(KERN_DEBUG "%s: %s", name, i ? " " : "buffer:"); for (j = 0; j < 8 && k < size; j++, k++) printk(" %02x", buffer[k]); printk("\n"); } } return;}/* * SB1000 commands for frame rx interrupt *//* receive a single frame and assemble datagram * (this is the heart of the interrupt routine) */static inline intsb1000_rx(struct net_device *dev){#define FRAMESIZE 184 unsigned char st[2], buffer[FRAMESIZE], session_id, frame_id; short dlen; int ioaddr, ns; unsigned int skbsize; struct sk_buff *skb; struct sb1000_private *lp = (struct sb1000_private *)dev->priv; struct net_device_stats *stats = &lp->stats; /* SB1000 frame constants */ const int FrameSize = FRAMESIZE; const int NewDatagramHeaderSkip = 8; const int NewDatagramHeaderSize = NewDatagramHeaderSkip + 18; const int NewDatagramDataSize = FrameSize - NewDatagramHeaderSize; const int ContDatagramHeaderSkip = 7; const int ContDatagramHeaderSize = ContDatagramHeaderSkip + 1; const int ContDatagramDataSize = FrameSize - ContDatagramHeaderSize; const int TrailerSize = 4; ioaddr = dev->base_addr; insw(ioaddr, (unsigned short*) st, 1);#ifdef XXXDEBUGprintk("cm0: received: %02x %02x\n", st[0], st[1]);#endif /* XXXDEBUG */ lp->rx_frames++; /* decide if it is a good or bad frame */ for (ns = 0; ns < NPIDS; ns++) { session_id = lp->rx_session_id[ns]; frame_id = lp->rx_frame_id[ns]; if (st[0] == session_id) { if (st[1] == frame_id || (!frame_id && (st[1] & 0xf0) == 0x30)) { goto good_frame; } else if ((st[1] & 0xf0) == 0x30 && (st[0] & 0x40)) { goto skipped_frame; } else { goto bad_frame; } } else if (st[0] == (session_id | 0x40)) { if ((st[1] & 0xf0) == 0x30) { goto skipped_frame; } else { goto bad_frame; } } } goto bad_frame;skipped_frame: stats->rx_frame_errors++; skb = lp->rx_skb[ns]; if (sb1000_debug > 1) printk(KERN_WARNING "%s: missing frame(s): got %02x %02x " "expecting %02x %02x\n", dev->name, st[0], st[1], skb ? session_id : session_id | 0x40, frame_id); if (skb) { dev_kfree_skb(skb); skb = 0; }good_frame: lp->rx_frame_id[ns] = 0x30 | ((st[1] + 1) & 0x0f); /* new datagram */ if (st[0] & 0x40) { /* get data length */ insw(ioaddr, buffer, NewDatagramHeaderSize / 2);#ifdef XXXDEBUGprintk("cm0: IP identification: %02x%02x fragment offset: %02x%02x\n", buffer[30], buffer[31], buffer[32], buffer[33]);#endif /* XXXDEBUG */ if (buffer[0] != NewDatagramHeaderSkip) { if (sb1000_debug > 1) printk(KERN_WARNING "%s: new datagram header skip error: " "got %02x expecting %02x\n", dev->name, buffer[0], NewDatagramHeaderSkip); stats->rx_length_errors++; insw(ioaddr, buffer, NewDatagramDataSize / 2); goto bad_frame_next; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -