diff -uNr module.orig/3cp4218.c module/3cp4218.c --- module.orig/3cp4218.c Tue Jul 9 08:47:08 2002 +++ module/3cp4218.c Thu Aug 15 05:35:44 2002 @@ -97,6 +97,7 @@ #define ADSL_Connection_Lost 0x41 #define ADSL_Open 0x03 #define ADSL_Close 0x04 +#define ADSL_Open_GDMT 0x03 #define ADSL_Open_ANSI 0x05 #define ADSL_Open_DMT 0x06 #define ADSL_Open_GLITE 0x07 @@ -132,7 +133,7 @@ MODULE_PARM(speed, "i"); MODULE_PARM_DESC(speed, "Driver speed: 0=normal 1=fast (default=0)"); MODULE_PARM(open, "i"); -MODULE_PARM_DESC(open, "Open mode: 5=ANSI 6=DMT 7=GLITE (default=5)"); +MODULE_PARM_DESC(open, "Open mode: 3=GDMT 5=ANSI 6=DMT 7=GLITE (default=5)"); /* usb_device_id struct */ @@ -203,6 +204,7 @@ struct usb_device *usb_dev; udsl_data_ctx_t *rcvbufs; struct sk_buff_head sndqueue; + unsigned char oambuff[64]; spinlock_t sndqlock; udsl_usb_send_data_context_t send_ctx[UDSL_NUMBER_SND_URBS]; int data_started; @@ -1305,7 +1307,7 @@ return -1; if (udsl_usb_write_status_byte(instance, 0x804c, 0x0f)) return -1; - if (open != ADSL_Open && open != ADSL_Open_ANSI && open != ADSL_Open_DMT && open != ADSL_Open_GLITE && open != ADSL_Open_MULTIMODE) + if (open != ADSL_Open && open != ADSL_Open_GDMT && open != ADSL_Open_ANSI && open != ADSL_Open_DMT && open != ADSL_Open_GLITE && open != ADSL_Open_MULTIMODE) open = ADSL_Open_ANSI; if (udsl_usb_write_status_byte(instance, TX_COMMAND, open)) return -1; @@ -1870,7 +1872,6 @@ } int remove_control_cells(unsigned char *source, int l, unsigned char *out, struct udsl_instance_data *instance) { - // TODO: check VPI, VCI OAM cells = user cells int number_of_cells; int total_length; unsigned char *target; @@ -1880,7 +1881,7 @@ unsigned short crc10_accum; urb_t *urb; int err; - unsigned char buf[64]; + unsigned char *buf = instance->oambuff; if (!source || l < 53 || (l % 53 != 0) || !out) return -1; @@ -1895,39 +1896,48 @@ control_cells++; if ((pti == ATM_PTI_E2EF5) && (source[(i*53)+5] == OAM_LOOPBACK)) { // Is OAM LOOPBACK cell? if (source[(i*53)+6] == 1) { // Return OAM LOOPBACK cell? - PDEBUG("OAM LOOPBACK cell detected:\n"); - PACKETDEBUG(source+(i*53), 53); - // Check CRC-10 - memset(buf, 0, 64); - memcpy(buf, source+(i*53), 53); - crc10_accum = update_crc10_by_bytes(0, (unsigned char *) &buf[5], 48); - if (crc10_accum != 0) - PDEBUG("Corruption detected in OAM LOOPBACK cell\n"); - else { - urb = usb_alloc_urb(0); - if (urb) { - buf[6]--; // unset loopback - buf[51] = 0; // if set last two 2 bytes (CRC) to zero then crc still is valid - buf[52] = 0; - crc10_accum = update_crc10_by_bytes(0, (unsigned char *) &buf[5], 48); - buf[51] ^= crc10_accum >> 8; - buf[52] ^= crc10_accum & 0xff; - FILL_BULK_URB(urb, - instance->usb_dev, - usb_sndbulkpipe(instance->usb_dev, UDSL_ENDPOINT_DATA_OUT), - &buf, - 64, - (usb_complete_t)send_complete, - instance - ); - urb->transfer_flags |= USB_QUEUE_BULK; - - PDEBUG("OAM LOOPBACK cell to return:\n"); - PACKETDEBUG(buf, 64); - - err = usb_submit_urb(urb); - if (err) - usb_free_urb(urb); + unsigned long atmhdr = ((unsigned long)(source[(i*53)+0]) << 24) + | ((unsigned long)(source[(i*53)+1]) << 16) + | ((unsigned long)(source[(i*53)+2]) << 8) + | (source[(i*53)+3] & 0xff); + unsigned short vpi = (atmhdr & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT; + unsigned long vci = (atmhdr & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT; + + if ((instance->modem_info.vpi == vpi) && (instance->modem_info.vci = vci)) { // Is the cell directed to our VPI.VCI? + PDEBUG("OAM LOOPBACK cell detected (vpi=%d, vci=%ld):\n", vpi, vci); + PACKETDEBUG(source+(i*53), 53); + // Check CRC-10 + memset(buf, 0, 64); + memcpy(buf, source+(i*53), 53); + crc10_accum = update_crc10_by_bytes(0, (unsigned char *) &buf[5], 48); + if (crc10_accum != 0) + PDEBUG("Corruption detected in OAM LOOPBACK cell\n"); + else { + urb = usb_alloc_urb(0); + if (urb) { + buf[6]--; // unset loopback + buf[51] = 0; // if set last two 2 bytes (CRC) to zero then crc still is valid + buf[52] = 0; + crc10_accum = update_crc10_by_bytes(0, (unsigned char *) &buf[5], 48); + buf[51] ^= crc10_accum >> 8; + buf[52] ^= crc10_accum & 0xff; + FILL_BULK_URB(urb, + instance->usb_dev, + usb_sndbulkpipe(instance->usb_dev, UDSL_ENDPOINT_DATA_OUT), + buf, + 64, + (usb_complete_t)send_complete, + instance + ); + urb->transfer_flags |= USB_QUEUE_BULK; + + PDEBUG("OAM LOOPBACK cell to return:\n"); + PACKETDEBUG(buf, 64); + + err = usb_submit_urb(urb); + if (err) + usb_free_urb(urb); + } } } }