mrtentry_t *switch_shortest_path(u_int32 source, u_int32 group) { mrtentry_t *mrtentry_ptr; /* TODO: XXX: prepare and send immediately the (S,G) join? */ if ((mrtentry_ptr = find_route(source, group, MRTF_SG, CREATE)) != (mrtentry_t *)NULL) { if (mrtentry_ptr->flags & MRTF_NEW) { mrtentry_ptr->flags &= ~MRTF_NEW; } else if (mrtentry_ptr->flags & MRTF_RP) { /* (S,G)RPbit with iif toward RP. Reset to (S,G) with iif * toward S. Delete the kernel cache (if any), because * change_interfaces() will reset it with iif toward S * and no data will arrive from RP before the switch * really occurs. */ mrtentry_ptr->flags &= ~MRTF_RP; mrtentry_ptr->incoming = mrtentry_ptr->source->incoming; mrtentry_ptr->upstream = mrtentry_ptr->source->upstream; delete_mrtentry_all_kernel_cache(mrtentry_ptr); change_interfaces(mrtentry_ptr, mrtentry_ptr->incoming, mrtentry_ptr->joined_oifs, mrtentry_ptr->pruned_oifs, mrtentry_ptr->leaves, mrtentry_ptr->asserted_oifs, 0); } SET_TIMER(mrtentry_ptr->timer, PIM_DATA_TIMEOUT); FIRE_TIMER(mrtentry_ptr->jp_timer); } return mrtentry_ptr; }
static int getMcdStatus(int timeout) { int st; McdTimeout = timeout; SET_TIMER(mcdStatTimer, 1); sleep_on(&mcd_waitq); if (McdTimeout <= 0) return -1; st = inb(MCDPORT(0)) & 0xFF; if (st == 0xFF) return -1; if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY) /* XXX might be an error? look at q-channel? */ audioStatus = CDROM_AUDIO_COMPLETED; if (st & MST_DSK_CHG) { mcdDiskChanged = 1; tocUpToDate = 0; audioStatus = CDROM_AUDIO_NO_STATUS; } return st; }
void do_pummel( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_SKYBLADE) ) { send_to_char("Huh?\n\r",ch); return; } if (ch->pcdata->powers[SKYBLADE_SKILLS] < 2) { send_to_char("You haven't mastered the skills abilities enough.\n\r",ch); return; } if (!TIME_UP(ch, TIMER_PUMMEL)) { send_to_char("You are too tired from the last time.\n\r",ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char("You aren't fighting anyone though.\n\r",ch); return; } if (IS_NPC(victim)) { send_to_char("They aren't stanced though.\n\r",ch); return; } SET_TIMER(ch, TIMER_PUMMEL, 5); do_stance(victim, ""); WAIT_STATE(victim,12); return; }
static void _flushData(int fd) { int rd = 0; struct itimerval ti, oti; char buf[1024]; int len = 1023; int count = 200; usleep(d4RdTimeout); /* for error handling in case of timeout */ timeoutGot = 0; /* set errno to 0 in order to get correct informations */ /* in case of error */ errno = 0; if (debugD4) fprintf(stderr, "flush data: length: %i\n", len); do { usleep(d4RdTimeout); SET_TIMER(ti,oti, d4RdTimeout); rd = read(fd, buf, len); if (debugD4) fprintf(stderr, "flush: read: %i %s\n", rd, rd < 0 && errno != 0 ?strerror(errno) : ""); RESET_TIMER(ti,oti); count--; } while ( count > 0 && (rd > 0 || (rd < 0 && errno == EAGAIN))); }
static void jig_response_complete(struct usb_ep *ep, struct usb_request *req) { struct psfreedom_device *dev = ep->driver_data; int status = req->status; unsigned long flags; spin_lock_irqsave (&dev->lock, flags); DBG (dev, "Jig response sent (status %d). Sent data so far : %d + %d\n", status, dev->response_len, req->length); switch (status) { case 0: /* normal completion */ if (ep == dev->in_ep) { /* our transmit completed. see if there's more to go. hub_transmit eats req, don't queue it again. */ dev->response_len += req->length; if (dev->response_len < 64) { jig_response_send (dev, req); } else { dev->status = DEVICE5_READY; SET_TIMER (150); } spin_unlock_irqrestore (&dev->lock, flags); return; } break; /* this endpoint is normally active while we're configured */ case -ECONNABORTED: /* hardware forced ep reset */ case -ESHUTDOWN: /* disconnect from host */ VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, req->actual, req->length); case -ECONNRESET: /* request dequeued */ hub_interrupt_queued = 0; spin_unlock_irqrestore (&dev->lock, flags); return; case -EOVERFLOW: /* buffer overrun on read means that * we didn't provide a big enough * buffer. */ default: DBG(dev, "%s complete --> %d, %d/%d\n", ep->name, status, req->actual, req->length); break; case -EREMOTEIO: /* short read */ break; } status = usb_ep_queue(ep, req, GFP_ATOMIC); if (status) { ERROR(dev, "kill %s: resubmit %d bytes --> %d\n", ep->name, req->length, status); usb_ep_set_halt(ep); /* FIXME recover later ... somehow */ } spin_unlock_irqrestore (&dev->lock, flags); }
/* Received challenge data */ static void jig_interrupt_complete(struct usb_ep *ep, struct usb_request *req) { struct psfreedom_device *dev = ep->driver_data; int status = req->status; unsigned long flags; spin_lock_irqsave (&dev->lock, flags); DBG (dev, "******Out interrupt complete (status %d) : length %d, actual %d\n", status, req->length, req->actual); switch (status) { case 0: /* normal completion */ if (ep == dev->out_ep) { /* our transmit completed */ /* TODO handle data */ dev->challenge_len += req->actual; DBG (dev, "******Challenge length : %d\n", dev->challenge_len); if (dev->challenge_len >= 64) { dev->status = DEVICE5_CHALLENGED; SET_TIMER (450); } } break; /* this endpoint is normally active while we're configured */ case -ECONNABORTED: /* hardware forced ep reset */ case -ECONNRESET: /* request dequeued */ case -ESHUTDOWN: /* disconnect from host */ VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, req->actual, req->length); spin_unlock_irqrestore (&dev->lock, flags); return; case -EOVERFLOW: /* buffer overrun on read means that * we didn't provide a big enough * buffer. */ default: DBG(dev, "%s complete --> %d, %d/%d\n", ep->name, status, req->actual, req->length); break; case -EREMOTEIO: /* short read */ break; } status = usb_ep_queue(ep, req, GFP_ATOMIC); if (status) { ERROR(dev, "kill %s: resubmit %d bytes --> %d\n", ep->name, req->length, status); usb_ep_set_halt(ep); /* FIXME recover later ... somehow */ } spin_unlock_irqrestore (&dev->lock, flags); }
static void hub_interrupt_complete(int flag, int size) { int flags; PRINTKI( "[%lu]Hub_interrupt_complete (status %d)\n",(jiffies-start_time)*10, flag); local_irq_save(flags); if (flag == 0) { //printk( "hub_interrupt_complete: ¿queda pendiente?\n"); hub_interrupt_queued = 0; } else { printk( "hub_interrupt_complete con error?: flag %d, size %d\n", flag, size); } local_irq_restore(flags); // Mask EP2 interrupts Ser0UDCCR = 0xFC; UDC_write(Ser0UDCCR, UDCCR_TIM); //UDC_write(Ser0UDCCR, UDCCR_TIM | UDCCR_REM); // Errata 29 if (device_retry>0) { PRINTKI( "[%lu]GetHub/PortStatus: retry port %d \n", (jiffies-start_time)*10, device_retry); } // Keep sending Device 5 connected until PORT_RESET received if (machine_state==DEVICE5_WAIT_READY && device_retry>0) { machine_state=DEVICE4_READY; SET_TIMER (10); } // Keep sending Device 3 disconnected until PORT_STATUS received if (machine_state==DEVICE3_WAIT_DISCONNECT && device_retry>0) { machine_state=DEVICE5_READY; SET_TIMER (10); } }
static void mcdStatTimer(void) { if (!(inb(MCDPORT(1)) & MFL_STATUS)) { wake_up(&mcd_waitq); return; } McdTimeout--; if (McdTimeout <= 0) { wake_up(&mcd_waitq); return; } SET_TIMER(mcdStatTimer, 1); }
void do_wyrmroar(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; one_argument (argument, arg); if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_SKYBLADE)) { send_to_char("Huh?\n\r",ch); return; } if (ch->pcdata->powers[SKYBLADE_SKILLS] < 9) { send_to_char("You have not mastered the skills ability enough yet.\n\r",ch); return; } if (!TIME_UP(ch, TIMER_WYRM_ROAR)) { send_to_char("Your throat is still sore from the last time.\n\r",ch); return; } if (( victim = get_char_room(ch, NULL, arg)) == NULL) { if (ch->fighting == NULL) { send_to_char("Yes release the roar of the wyrm, but at who?\n\r",ch); return; } else victim = ch->fighting; } if (victim == ch) { send_to_char("Quit that stupid ass.\n\r",ch); return; } if (is_safe(ch, victim)) return; SET_TIMER(ch, TIMER_WYRM_ROAR, 6); WAIT_STATE(victim, 18); act("$n roars with the power of the wyrm, stunning you in place.",ch,NULL,victim,TO_VICT); act("$n roars with the power of the wyrm, stunning $N in place.", ch, NULL, victim, TO_NOTVICT); act("You roar with the power of the wyrm, stunning $N in place.", ch, NULL, victim, TO_CHAR); return; }
static void gscd_read_cmd (void) { long block; struct gscd_Play_msf gscdcmd; char cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 }; /* cmd mode M-S-F secth sectl */ cmd_status (); if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) ) { printk ( "GSCD: no disk or door open\n" ); end_request (0); } else { if ( disk_state & ST_INVALID ) { printk ( "GSCD: disk invalid\n" ); end_request (0); } else { gscd_bn = -1; /* purge our buffer */ block = CURRENT -> sector / 4; gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */ cmd[2] = gscdcmd.start.min; cmd[3] = gscdcmd.start.sec; cmd[4] = gscdcmd.start.frame; #ifdef GSCD_DEBUG printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] ); #endif cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 ); gscd_bn = CURRENT -> sector / 4; gscd_transfer(); end_request(1); } } SET_TIMER(__do_gscd_request, 1); }
static void do_mcd_request(void) { #ifdef TEST2 printk(" do_mcd_request(%ld+%ld)\n", CURRENT -> sector, CURRENT -> nr_sectors); #endif mcd_transfer_is_active = 1; while (CURRENT_VALID) { if (CURRENT->bh) { if (!buffer_locked(CURRENT->bh)) panic(DEVICE_NAME ": block not locked"); } mcd_transfer(); if (CURRENT -> nr_sectors == 0) { end_request(1); } else { mcd_buf_out = -1; /* Want to read a block not in buffer */ if (mcd_state == MCD_S_IDLE) { if (!tocUpToDate) { if (updateToc() < 0) { while (CURRENT_VALID) end_request(0); break; } } mcd_state = MCD_S_START; McdTries = 5; SET_TIMER(mcd_poll, 1); } break; } } mcd_transfer_is_active = 0; #ifdef TEST2 printk(" do_mcd_request ends\n"); #endif }
/* * The setup() callback implements all the ep0 functionality that's * not handled lower down, in hardware or the hardware driver (like * device and endpoint feature flags, and their status). It's all * housekeeping for the gadget function we're implementing. Most of * the work is in config-specific setup. */ static int devices_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl, u16 request, u16 w_index, u16 w_value, u16 w_length) { struct psfreedom_device *dev = get_gadget_data(gadget); struct usb_request *req = dev->req; int value = -EOPNOTSUPP; /* usually this stores reply data in the pre-allocated ep0 buffer, * but config change events will reconfigure hardware. */ switch (ctrl->bRequest) { case USB_REQ_GET_DESCRIPTOR: if ((ctrl->bRequestType & USB_DIR_IN) == 0) { goto unknown; } switch (w_value >> 8) { case USB_DT_DEVICE: switch (dev->current_port) { case 1: value = min(w_length, (u16) sizeof(port1_device_desc)); memcpy(req->buf, port1_device_desc, value); break; case 2: value = min(w_length, (u16) sizeof(port2_device_desc)); memcpy(req->buf, port2_device_desc, value); break; case 3: value = min(w_length, (u16) sizeof(port3_device_desc)); memcpy(req->buf, port3_device_desc, value); break; case 4: value = min(w_length, (u16) sizeof(port4_device_desc)); memcpy(req->buf, port4_device_desc, value); break; case 5: value = min(w_length, (u16) sizeof(port5_device_desc)); memcpy(req->buf, port5_device_desc, value); break; case 6: value = min(w_length, (u16) sizeof(port6_device_desc)); memcpy(req->buf, port6_device_desc, value); break; default: value = -EINVAL; break; } break; case USB_DT_CONFIG: value = 0; switch (dev->current_port) { case 1: if ((w_value & 0xff) < 4) { if (w_length == 8) { value = sizeof(port1_short_config_desc); memcpy(req->buf, port1_short_config_desc, value); } else { value = dev->port1_config_desc_size; memcpy(req->buf, dev->port1_config_desc, value); } if ((w_value & 0xff) == 3 && w_length > 8) { dev->status = DEVICE1_READY; SET_TIMER (100); } } break; case 2: value = sizeof(port2_config_desc); memcpy(req->buf, port2_config_desc, value); if (w_length > 8) { dev->status = DEVICE2_READY; SET_TIMER (150); } break; case 3: value = sizeof(port3_config_desc); memcpy(req->buf, port3_config_desc, value); if ((w_value & 0xff) == 1 && w_length > 8) { dev->status = DEVICE3_READY; SET_TIMER (80); } break; case 4: if ((w_value & 0xff) == 0) { value = sizeof(port4_config_desc_1); memcpy(req->buf, port4_config_desc_1, value); } else if ((w_value & 0xff) == 1) { if (w_length == 8) { value = sizeof(port4_short_config_desc_2); memcpy(req->buf, port4_short_config_desc_2, value); } else { value = sizeof(port4_config_desc_2); memcpy(req->buf, port4_config_desc_2, value); } } else if ((w_value & 0xff) == 2) { value = sizeof(port4_config_desc_3); memcpy(req->buf, port4_config_desc_3, value); if (w_length > 8) { dev->status = DEVICE4_READY; SET_TIMER (180); } } break; case 5: value = sizeof(port5_config_desc); memcpy(req->buf, port5_config_desc, value); break; case 6: value = sizeof(port6_config_desc); memcpy(req->buf, port6_config_desc, value); break; default: value = -EINVAL; break; } if (value >= 0) value = min(w_length, (u16)value); break; case USB_DT_STRING: value = 0; break; } break; case USB_REQ_SET_CONFIGURATION: if (dev->current_port == 5) { DBG (dev, "SET CONFIGURATION ON JIG\n"); jig_set_config(dev, 0); } value = 0; break; case USB_REQ_GET_CONFIGURATION: case USB_REQ_GET_STATUS: case USB_REQ_SET_INTERFACE: if (dev->current_port == 5) DBG (dev, "SET INTERFACE ON JIG\n"); value = 0; break; case USB_REQ_GET_INTERFACE: if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) { goto unknown; } *(u8 *)req->buf = 0; value = min(w_length, (u16)1); break; case 0xAA: INFO (dev, "JAILBROKEN!!! DONE!!!!!!!!!\n"); dev->status = DEVICE6_READY; SET_TIMER (0); value = 0; break; default: unknown: DBG(dev, "unknown control req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); } /* device either stalls (value < 0) or reports success */ return value; }
/* * The setup() callback implements all the ep0 functionality that's * not handled lower down, in hardware or the hardware driver (like * device and endpoint feature flags, and their status). It's all * housekeeping for the gadget function we're implementing. Most of * the work is in config-specific setup. */ static int hub_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl, u16 request, u16 w_index, u16 w_value, u16 w_length) { struct psfreedom_device *dev = get_gadget_data(gadget); struct usb_request *req = dev->req; int value = -EOPNOTSUPP; /* usually this stores reply data in the pre-allocated ep0 buffer, * but config change events will reconfigure hardware. */ switch (ctrl->bRequest) { case USB_REQ_GET_DESCRIPTOR: if ((ctrl->bRequestType & USB_DIR_IN) == 0) { goto unknown; } if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) { /* GET_HUB_DESCRIPTOR Class specific request */ value = min(w_length, (u16) sizeof(hub_header_desc)); memcpy(req->buf, &hub_header_desc, value); if (value >= 0) value = min(w_length, (u16)value); } else { switch (w_value >> 8) { case USB_DT_DEVICE: value = min(w_length, (u16) sizeof(hub_device_desc)); memcpy(req->buf, &hub_device_desc, value); break; case USB_DT_CONFIG: memcpy(req->buf, &hub_config_desc, sizeof(hub_config_desc)); value = sizeof(hub_config_desc); memcpy (req->buf + value, &hub_interface_desc, sizeof(hub_interface_desc)); value += sizeof(hub_interface_desc); memcpy (req->buf + value, &hub_endpoint_desc, sizeof(hub_endpoint_desc)); value += sizeof(hub_endpoint_desc); if (value >= 0) value = min(w_length, (u16)value); break; case USB_DT_STRING: value = 0; break; } } break; case USB_REQ_SET_CONFIGURATION: if (ctrl->bRequestType != 0) { goto unknown; } value = hub_set_config(dev, w_value); break; case USB_REQ_GET_CONFIGURATION: if (ctrl->bRequestType != USB_DIR_IN) { goto unknown; } *(u8 *)req->buf = 0; value = min(w_length, (u16)1); break; case USB_REQ_SET_INTERFACE: if (ctrl->bRequestType != USB_RECIP_INTERFACE) { goto unknown; } value = 0; break; case USB_REQ_GET_INTERFACE: if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) { goto unknown; } if (w_index >= 1) { value = -EDOM; break; } *(u8 *)req->buf = 0; value = min(w_length, (u16)1); break; case USB_REQ_SET_FEATURE: if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) { switch (ctrl->bRequestType & USB_RECIP_MASK) { /* SET_HUB_FEATURE */ case USB_RECIP_DEVICE: switch (w_value) { case 0: /* C_HUB_LOCAL_POWER */ case 1: /* C_HUB_OVER_CURRENT */ VDBG (dev, "SetHubFeature called\n"); value = 0; break; default: value = -EINVAL; break; } break; case USB_RECIP_OTHER: /* SET_PORT_FEATURE */ if (w_index == 0 || w_index > 6) { DBG (dev, "SetPortFeature: invalid port index %d\n", w_index); value = -EINVAL; break; } switch (w_value) { case 4: /* PORT_RESET */ DBG (dev, "SetPortFeature PORT_RESET called\n"); dev->hub_ports[w_index-1].change |= PORT_STAT_C_RESET; hub_port_changed (dev); value = 0; break; case 8: /* PORT_POWER */ DBG (dev, "SetPortFeature PORT_POWER called\n"); dev->hub_ports[w_index-1].status |= PORT_STAT_POWER; if (dev->status == INIT && w_index == 6) { dev->status = HUB_READY; SET_TIMER (150); } value = 0; break; case 0: /* PORT_CONNECTION */ case 1: /* PORT_ENABLE */ case 2: /* PORT_SUSPEND */ case 3: /* PORT_OVER_CURRENT */ case 9: /* PORT_LOW_SPEED */ case 16: /* C_PORT_CONNECTION */ case 17: /* C_PORT_ENABLE */ case 18: /* C_PORT_SUSPEND */ case 19: /* C_PORT_OVER_CURRENT */ case 20: /* C_PORT_RESET */ case 21: /* PORT_TEST */ case 22: /* PORT_INDICATOR */ DBG (dev, "SetPortFeature called\n"); value = 0; break; default: value = -EINVAL; break; } break; } } break; case USB_REQ_CLEAR_FEATURE: if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) { switch (ctrl->bRequestType & USB_RECIP_MASK) { /* CLEAR_HUB_FEATURE */ case USB_RECIP_DEVICE: switch (w_value) { case 0: /* C_HUB_LOCAL_POWER */ case 1: /* C_HUB_OVER_CURRENT */ VDBG (dev, "ClearHubFeature called\n"); value = 0; break; default: value = -EINVAL; break; } break; case USB_RECIP_OTHER: /* CLEAR_PORT_FEATURE */ if (w_index == 0 || w_index > 6) { DBG (dev, "ClearPortFeature: invalid port index %d\n", w_index); value = -EINVAL; break; } switch (w_value) { case 0: /* PORT_CONNECTION */ case 1: /* PORT_ENABLE */ case 2: /* PORT_SUSPEND */ case 3: /* PORT_OVER_CURRENT */ case 4: /* PORT_RESET */ case 8: /* PORT_POWER */ case 9: /* PORT_LOW_SPEED */ value = 0; break; case 16: /* C_PORT_CONNECTION */ DBG (dev, "ClearPortFeature C_PORT_CONNECTION called\n"); dev->hub_ports[w_index-1].change &= ~PORT_STAT_C_CONNECTION; switch (dev->status) { case DEVICE1_WAIT_DISCONNECT: dev->status = DEVICE1_DISCONNECTED; SET_TIMER (200); break; case DEVICE2_WAIT_DISCONNECT: dev->status = DEVICE2_DISCONNECTED; SET_TIMER (170); break; case DEVICE3_WAIT_DISCONNECT: dev->status = DEVICE3_DISCONNECTED; SET_TIMER (450); break; case DEVICE4_WAIT_DISCONNECT: dev->status = DEVICE4_DISCONNECTED; SET_TIMER (200); break; case DEVICE5_WAIT_DISCONNECT: dev->status = DEVICE5_DISCONNECTED; SET_TIMER (200); break; default: break; } value = 0; break; case 20: /* C_PORT_RESET */ DBG (dev, "ClearPortFeature C_PORT_RESET called\n"); dev->hub_ports[w_index-1].change &= ~PORT_STAT_C_RESET; switch (dev->status) { case DEVICE1_WAIT_READY: if (w_index == 1) dev->switch_to_port_delayed = w_index; break; case DEVICE2_WAIT_READY: if (w_index == 2) dev->switch_to_port_delayed = w_index; break; case DEVICE3_WAIT_READY: if (w_index == 3) dev->switch_to_port_delayed = w_index; break; case DEVICE4_WAIT_READY: if (w_index == 4) dev->switch_to_port_delayed = w_index; break; case DEVICE5_WAIT_READY: if (w_index == 5) dev->switch_to_port_delayed = w_index; break; case DEVICE6_WAIT_READY: if (w_index == 6) dev->switch_to_port_delayed = w_index; break; default: break; } /* Delay switching the port because we first need to response to this request with the proper address */ if (dev->switch_to_port_delayed >= 0) SET_TIMER (0); value = 0; break; case 17: /* C_PORT_ENABLE */ case 18: /* C_PORT_SUSPEND */ case 19: /* C_PORT_OVER_CURRENT */ case 21: /* PORT_TEST */ case 22: /* PORT_INDICATOR */ DBG (dev, "ClearPortFeature called\n"); value = 0; break; default: value = -EINVAL; break; } break; } } break; case USB_REQ_GET_STATUS: if ((ctrl->bRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS) { u16 status = 0; u16 change = 0; value = 2 * sizeof (u16); switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: /* GET_HUB_STATUS */ status = 0; change = 0; break; case USB_RECIP_OTHER: /* GET_PORT_STATUS */ if (w_index == 0 || w_index > 6) { DBG (dev, "GetPortstatus : invalid port index %d\n", w_index); value = -EINVAL; break; } status = dev->hub_ports[w_index -1].status; change = dev->hub_ports[w_index -1].change; break; default: goto unknown; } if (value > 0) { DBG (dev, "GetHub/PortStatus: transmtiting status %d change %d\n", status, change); status = cpu_to_le16 (status); change = cpu_to_le16 (change); memcpy(req->buf, &status, sizeof(u16)); memcpy(req->buf + sizeof(u16), &change, sizeof(u16)); } } break; default: unknown: ERROR (dev, "unknown control req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); } /* device either stalls (value < 0) or reports success */ return value; }
static void wd_proc(void) { static byte am[6]; byte i_met; word stat = 0; static /*PROGMEM */void * entries[] = { ADDR(t0), ADDR(t0_cmd), ADDR(t1), ADDR(t1_set), ADDR(t1_trkupd), ADDR(t1_trk0), ADDR(t1_step), ADDR(t1_waits), ADDR(t1_vrfy), ADDR(t1_waitd), ADDR(t1_hlt), ADDR(t1_rdam), ADDR(t2), ADDR(t2_waitd), ADDR(t2_hlt), ADDR(t2_loop), ADDR(t2_amc), ADDR(t2_rd), ADDR(t2_rdblk), ADDR(t2_mchk), ADDR(t2_wr), ADDR(t3), ADDR(t3_wait), ADDR(t3_hlt), ADDR(t3_rdam), ADDR(t4), ADDR(reset), ADDR(done) }; goto *entries[wd.state]; /***************/ ENTRY(t0); /***************/ WAIT(); /***************/ ENTRY(t0_cmd); /***************/ WD_TRACE(("wd: t0_cmd: %s, cr=0x%02x\n", wd_command_decode(wd.cr), wd.cr)); if ((wd.cr & TYPEIV_MASK) == TYPEIV) { BDI_ResetWrite(); BDI_ResetRead( 0 ); if ((wd.cr & INTR_MASK) != 0) { wd.ready = fdc_query(FDC_READY); SET_TIMERU( 64 ); JUMP(t4); } if (!WD_BUSY()) { wd.cr_c = 0; } WD_TRACE(("wd: clr busy signal (#1)\n")); WD_CLR_BUSY(); JUMP(t0); } else if ((wd.cr & TYPEI_MASK) == TYPEI) { wd.cr_c = wd.cr; wd.str &= ~(WD17XX_STAT_CRCERR|WD17XX_STAT_SEEKERR); fdc_set(FDC_HLD, (wd.cr_c & TYPEI_BIT_H) != 0); JUMP(t1); } else { wd.cr_c = wd.cr; wd.str &= ~(WD17XX_STAT_RECTYPE|WD17XX_STAT_WRERR|WD17XX_STAT_CRCERR|WD17XX_STAT_LOST|WD17XX_STAT_WP|WD17XX_STAT_NOTFOUND); if (!fdc_query(FDC_READY)) { JUMP(done); } fdc_set(FDC_HLD, 1); if ((wd.cr_c & TYPEII_MASK) == TYPEII) { JUMP(t2); } else { if ((wd.cr_c & TYPEIII_AM_MASK) != TYPEIII_AM) { wd.str |= WD17XX_STAT_WP; JUMP(done); } JUMP(t3); } } WAIT(); //========================================================= // type 1 //========================================================= /***************/ ENTRY(t1); /***************/ WD_TRACE(("wd: t1: dr=%x, hld=%u\n", wd.dr, fdc_query(FDC_HLD))); if ((wd.cr_c & TYPEI_STEP_MASK) != 0) { if ((wd.cr_c & TYPEI_STEPWD_MASK) == TYPEI_STEPWD) { fdc_set(FDC_SDIR, (wd.cr_c & TYPEI_SDIR_MASK) == 0); } if ((wd.cr_c & TYPEI_BIT_U)) { JUMP(t1_trkupd); } else { JUMP(t1_step); } } else { if ((wd.cr_c & TYPEI_SEEK_MASK) != TYPEI_SEEK) { // restore wd.tr = 0xff; wd.dr = 0; } } /***************/ ENTRY(t1_set); /***************/ WD_TRACE(("wd: t1_set, time=%s\n", ticks_str(get_ticks()))); wd.dsr = wd.dr; if (wd.dsr == wd.tr) { JUMP(t1_vrfy); } fdc_set(FDC_SDIR, wd.dsr > wd.tr); /***************/ ENTRY(t1_trkupd); /***************/ WD_TRACE(("wd: t1_trkupd, sdir=%u, tr=%u, time=%s\n", fdc_query(FDC_SDIR), wd.tr, ticks_str(get_ticks()))); if (fdc_query(FDC_SDIR)) { wd.tr += 1; } else { wd.tr -= 1; } /***************/ ENTRY(t1_trk0); /***************/ WD_TRACE(("wd: t1_trk0, sdir=%u, time=%s\n", fdc_query(FDC_SDIR), ticks_str(get_ticks()))); if (!fdc_query(FDC_TRK0) && !fdc_query(FDC_SDIR)) { WD_TRACE(("wd: t1_trk0: trk0\n")); wd.tr = 0; JUMP(t1_vrfy); } else { fdc_set(FDC_STEP, 1); SET_TIMERU(WD_STEP_INTERVAL); } /***************/ ENTRY(t1_step); /***************/ WDH_TRACE(("wd: t1_step time=%s\n", ticks_str(get_ticks()))); WAIT_TIMER(); fdc_set(FDC_STEP, 0); SET_TIMER(wd_step_rate(wd.cr_c & TYPEI_BIT_R)); /***************/ ENTRY(t1_waits); /***************/ WDH_TRACE(("wd: t1_waits time=%s\n", ticks_str(get_ticks()))); // delay according to r1,r0 field WAIT_TIMER(); if ((wd.cr_c & 0xe0) == 0) { JUMP(t1_set); } /***************/ ENTRY(t1_vrfy); /***************/ WD_TRACE(("wd: t1_vrfy time=%s\n", ticks_str(get_ticks()))); // is V = 1? if ((wd.cr_c & TYPEI_BIT_V) == 0) { JUMP(done); } // set hld fdc_set(FDC_HLD, 1); // setup delay SET_TIMER(DATA_DELAY); /***************/ ENTRY(t1_waitd); /***************/ WDH_TRACE(("wd: t1_waitd time=%s\n", ticks_str(get_ticks()))); // has 15 ms expired WAIT_TIMER(); /***************/ ENTRY(t1_hlt); /***************/ WD_TRACE(("wd: t1_hlt time=%s\n", ticks_str(get_ticks()))); // is hlt = 1 if (!wd_is_hld()) { WAIT(); } wd.icnt = 0; /***************/ ENTRY(t1_rdam); /***************/ WD_TRACE(("wd: t1_rdam, icnt=%u, time=%s\n", wd.icnt, ticks_str(get_ticks()))); if (wd.icnt >= 6) { wd.str |= WD17XX_STAT_SEEKERR; JUMP(done); } stat = floppy_stat(); if ((stat & FLP_STAT_AM) == 0) { WAIT(); } if (wd_rd_am(am)) { if (wd.tr == am[0]) { JUMP(done); } } WAIT(); //========================================================= // type 2 //========================================================= /***************/ ENTRY(t2); /***************/ WD_TRACE(("wd: t2 tr=%u, sr=%u, side=%u, cr=%x, time=%s\n", wd.tr, wd.sr, wd.cr_c & TYPEII_BIT_S ? 1 : 0, wd.cr_c, ticks_str(get_ticks()))); floppy_set_sec_id(wd.sr); if ((wd.cr_c & TYPEII_BIT_E) == 0) { JUMP(t2_hlt); } SET_TIMER(DATA_DELAY); /***************/ ENTRY(t2_waitd); /***************/ WDH_TRACE(("wd: t2_waitd time=%s\n", ticks_str(get_ticks()))); WAIT_TIMER(); /***************/ ENTRY(t2_hlt); /***************/ WD_TRACE(("wd: t2_hlt time=%s\n", ticks_str(get_ticks()))); if (!wd_is_hld()) { WAIT(); } // TG43 /***************/ ENTRY(t2_loop); /***************/ WD_TRACE(("wd: t2_loop time=%s\n", ticks_str(get_ticks()))); if ((wd.cr_c & TYPEII_WR_MASK) == TYPEII_WR) { if (fdc_query(FDC_WP)) { WD_TRACE(("wd: t2_loop disk is wp\n")); wd.str |= WD17XX_STAT_WP; JUMP(done); } } wd.icnt = 0; /***************/ ENTRY(t2_amc); /***************/ if (wd.icnt >= 6) { wd.str |= WD17XX_STAT_NOTFOUND; JUMP(done); } stat = floppy_stat(); if ((stat & FLP_STAT_AM) == 0) { WAIT(); } if (!wd_rd_am(am)) { JUMP(done); } WD_TRACE(("wd: t2_amc, sz=%u (trk,side,sec) dsk(%u,%u,%u) wd(%u,%u,%u) time=%s\n", am[3], am[0], am[1], am[2], wd.tr, wd.cr_c & TYPEII_BIT_S ? 1 : 0, wd.sr, ticks_str(get_ticks()))); if (wd.tr != am[0]) { if( floppy_fast_mode ) { wd.str |= WD17XX_STAT_NOTFOUND; JUMP(done); } else WAIT(); } if (wd.sr != am[2]) { WAIT(); } // 1795 - other operation if ( (wd.cr_c & TYPEII_BIT_C) != 0 ) { byte side = ( wd.cr_c & TYPEII_BIT_S ) != 0 ? 0 : 1; if ( side == am[1] ) { WAIT(); } } wd.dcnt = wd_sect_size(am[3]); BDI_ResetWrite(); SET_TIMER_DCNT( wd.dcnt ); if ((wd.cr_c & TYPEII_WR_MASK) == TYPEII_WR) { BDI_ResetRead( wd.dcnt - 1 ); WD_TRACE(("wd: t2_amc, SET_DRQ() time=%s\n", ticks_str(get_ticks()))); WD_SET_DRQ(); JUMP(t2_wr); } /***************/ ENTRY(t2_rd); /***************/ WD_TRACE(("wd: t2_rd time=%s\n", ticks_str(get_ticks()))); stat = floppy_stat(); if ((stat & FLP_STAT_AM) != 0) { wd.str |= WD17XX_STAT_NOTFOUND; JUMP(done); } // put record type in status reg bit 5 if ((stat & FLP_STAT_DEL) != 0) { wd.str |= WD17XX_STAT_RECTYPE; // 1 = deleted record, 0 - normal record } else { wd.str &= ~WD17XX_STAT_RECTYPE; // 1 = deleted record, 0 - normal record } /***************/ ENTRY(t2_rdblk); /***************/ WDH_TRACE(("wd: t2_rdblk dcnt=%u, time=%s\n", wd.dcnt, ticks_str(get_ticks()))); while( wd.dcnt > 1 ) { wd_floppy_read(); BDI_Write( wd.dsr ); wd.dcnt--; } // has first byte been assembled in dsr if (!WD_DRQ()) { t2_rd_common: if (wd.dcnt == 0) { stat = floppy_stat(); if( ( stat & FLP_STAT_ERR ) != 0 ) wd.str |= WD17XX_STAT_CRCERR; if( ( wd.str & WD17XX_STAT_CRCERR ) != 0 ) JUMP(done); JUMP(t2_mchk); } wd_floppy_read(); wd.dr = wd.dsr; wd.dcnt -= 1; WD_SET_DRQ(); } else { if (TIMER_EXP()) { WD_TRACE(("wd: t2_rdblk - set LOST, time=%s (byte time=%s, drq time=%s)\n", ticks_str(get_ticks()), ticks_str1(wd.delta_time), ticks_str2(wd.start_time))); //__TRACE( "wd: t2_rdblk - set LOST\n" ); wd.str |= WD17XX_STAT_LOST; wd.str |= WD17XX_STAT_CRCERR; BDI_ResetWrite(); goto t2_rd_common; } } WAIT(); /***************/ ENTRY(t2_mchk); /***************/ WD_TRACE(("wd: t2_mchk wdstat=%x, flp_stat=%x, time=%s\n", wd.str, stat, ticks_str(get_ticks()))); if ((wd.cr_c & TYPEII_BIT_M) != 0) { wd.sr += 1; JUMP(t2_loop); } WD_TRACE(("wd: end of read\n")); JUMP(done); /***************/ ENTRY(t2_wr); /***************/ WDH_TRACE(("wd: t2_wr dcnt=%u, time=%s\n", wd.dcnt, ticks_str(get_ticks()))); while( BDI_Read( &wd.dsr ) ) { wd_floppy_write(); wd.dcnt--; } if (!WD_DRQ()) { wd.dsr = wd.dr; t2_wr_common: wd_floppy_write(); wd.dcnt -= 1; if (wd.dcnt == 0) { stat = floppy_stat(); if( ( stat & FLP_STAT_ERR ) != 0 ) wd.str |= WD17XX_STAT_CRCERR; if( ( wd.str & WD17XX_STAT_CRCERR ) != 0 ) JUMP(done); JUMP(t2_mchk); } WD_SET_DRQ(); } else { if (TIMER_EXP()) { WD_TRACE(("wd: t2_wr - set LOST, time=%s (byte time=%s, drq time=%s)\n", ticks_str(get_ticks()), ticks_str1(wd.delta_time), ticks_str2(wd.start_time))); //__TRACE( "wd: t2_wr - set LOST\n" ); BDI_ResetRead(0); wd.str |= WD17XX_STAT_LOST; wd.str |= WD17XX_STAT_CRCERR; wd.dsr = 0; goto t2_wr_common; } } WAIT(); //========================================================= // type 3 //========================================================= /***************/ ENTRY(t3); /***************/ WD_TRACE(("wd: t3 time=%s\n", ticks_str(get_ticks()))); if ((wd.cr_c & TYPEIII_BIT_E) == 0) { JUMP(t3_hlt); } SET_TIMER(DATA_DELAY); /***************/ ENTRY(t3_wait); /***************/ WDH_TRACE(("wd: t3_wait time=%s\n", ticks_str(get_ticks()))); WAIT_TIMER(); /***************/ ENTRY(t3_hlt); /***************/ WD_TRACE(("wd: t3_hlt time=%s\n", ticks_str(get_ticks()))); if (!wd_is_hld()) { WAIT(); } wd.icnt = 0; wd.dcnt = 6; wd_crc_init(); BDI_ResetWrite(); /***************/ ENTRY(t3_rdam); /***************/ WDH_TRACE(("wd: t3_rdam time=%s\n", ticks_str(get_ticks()))); if (wd.icnt >= 6) { wd.str |= WD17XX_STAT_NOTFOUND; JUMP(done); } if (wd.dcnt == 6) { stat = floppy_stat(); if ((stat & FLP_STAT_AM) == 0) { WAIT(); } } while( wd.dcnt > 1 ) { wd_floppy_read(); BDI_Write( wd.dsr ); wd.dcnt--; } if (!WD_DRQ()) { if (wd.dcnt == 0) { WD_TRACE(("wd: rd_am, crc=0x%04x\n", wd.crc)); WD_TRACE(("wd: rd_am (%u,%u,%u,%u), crc=0x%02x%02x\n", am[5], am[4], am[3], am[2], am[1], am[0])); if (wd.crc != 0) { wd.str |= WD17XX_STAT_CRCERR; } JUMP(done); } wd_floppy_read(); wd.dr = wd.dsr; wd.dcnt -= 1; #if defined(DEBUG) && DEBUG am[wd.dcnt] = wd.dsr; #endif if (wd.dcnt == 5) { wd.sr = wd.dsr; } WD_SET_DRQ(); } WAIT(); //========================================================= // type 4 //========================================================= /***************/ ENTRY(t4); /***************/ WAIT_TIMER(); i_met = INTR_MASK_I3; if (wd.ready != fdc_query(FDC_READY)) { i_met |= wd.ready ? INTR_MASK_I1 : INTR_MASK_I0; wd.ready = !wd.ready; } if (wd.index) { i_met |= INTR_MASK_I2; } if ((i_met & wd.cr & INTR_MASK) == 0) { WAIT(); } JUMP(done); /***************/ ENTRY(reset); /***************/ WAIT(); /***************/ ENTRY(done); /***************/ fdc_set(FDC_STEP, 0); WD_TRACE(("wd: clr busy signal (#2)\n\n")); WD_CLR_BUSY(); //WD_CLR_DRQ(); WD_SET_INT(); STATE(t0); }
hd_timer () { register struct hdcb *hdp; register int s = splimp (); for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) { if (hdp->hd_rrtimer && (--hdp->hd_rrtimer == 0)) { if (hdp->hd_lasttxnr != hdp->hd_vr) hd_writeinternal (hdp, RR, POLLOFF); } if (!(hdp->hd_timer && --hdp->hd_timer == 0)) continue; switch (hdp->hd_state) { case INIT: case DISC_SENT: hd_writeinternal (hdp, DISC, POLLON); break; case ABM: if (hdp->hd_lastrxnr != hdp->hd_vs) { /* XXX */ hdp->hd_timeouts++; hd_resend_iframe (hdp); } break; case WAIT_SABM: hd_writeinternal (hdp, FRMR, POLLOFF); if (++hdp->hd_retxcnt == hd_n2) { hdp->hd_retxcnt = 0; hd_writeinternal (hdp, SABM, POLLOFF); hdp->hd_state = WAIT_UA; } break; case DM_SENT: if (++hdp->hd_retxcnt == hd_n2) { /* Notify the packet level. */ (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp); hdp->hd_retxcnt = 0; hdp->hd_state = SABM_SENT; hd_writeinternal (hdp, SABM, POLLOFF); } else hd_writeinternal (hdp, DM, POLLOFF); break; case WAIT_UA: if (++hdp->hd_retxcnt == hd_n2) { hdp->hd_retxcnt = 0; hd_writeinternal (hdp, DM, POLLOFF); hdp->hd_state = DM_SENT; } else hd_writeinternal (hdp, SABM, POLLOFF); break; case SABM_SENT: /* Do this indefinitely. */ hd_writeinternal (hdp, SABM, POLLON); break; case DISCONNECTED: /* * Poll the interface driver flags waiting * for the IFF_UP bit to come on. */ if (hdp->hd_ifp->if_flags & IFF_UP) hdp->hd_state = INIT; } SET_TIMER (hdp); } splx (s); }
static int _readData(int fd, unsigned char *buf, int len) { int rd = 0; int total = 0; int toGet = 0; unsigned char header[6]; struct timeval beg, end; long dt; struct itimerval ti, oti; /* set errno to 0 in order to get correct informations */ /* in case of error */ errno = 0; /* read the first 6 bytes */ gettimeofday(&beg, NULL); while ( total < 6 ) { SET_TIMER(ti,oti, d4RdTimeout); rd = read(fd, header+total, 6-total); RESET_TIMER(ti,oti); if ( rd <= 0 ) { gettimeofday(&end, NULL); dt = (end.tv_sec - beg.tv_sec) * 1000; dt += (end.tv_usec - beg.tv_usec) / 1000; if ( dt > d4RdTimeout*3 ) { if ( debugD4 ) fprintf(stderr,"Timeout at _readData(), dt = %ld ms\n", dt); return -1; break; } continue; } else { total += rd; } } if ( debugD4 ) printHexValues("Recv: ",header,total); if ( total == 6 ) { toGet = (header[2] >> 8) + header[3] - 6; if (debugD4) fprintf(stderr, "toGet: %i\n", toGet); if (toGet > len) return -1; total = 0; gettimeofday(&beg, NULL); while ( total < toGet ) { SET_TIMER(ti,oti, d4RdTimeout); rd = read(fd, buf+total, toGet-total); RESET_TIMER(ti,oti); if ( rd <= 0 ) { gettimeofday(&end, NULL); dt = (end.tv_sec - beg.tv_sec) * 1000; dt += (end.tv_usec - beg.tv_usec) / 1000; if ( dt > d4RdTimeout*3 ) { if ( debugD4 ) fprintf(stderr,"Timeout at _readData(), dt = %ld ms\n",dt); return -1; break; } continue; } else { total += rd; } } if ( debugD4 ) printHexValues("Recv: ",buf,total); return total; }
int readAnswer(int fd, unsigned char *buf, int len) { int rd = 0; int total = 0; struct timeval beg, end; struct itimerval ti, oti; long dt; int count = 0; int first_read = 1; /* wait a little bit before reading an answer */ usleep(d4RdTimeout); /* for error handling in case of timeout */ timeoutGot = 0; /* set errno to 0 in order to get correct informations */ /* in case of error */ errno = 0; gettimeofday(&beg, NULL); if (debugD4) fprintf(stderr, "length: %i\n", len); while ( total < len ) { SET_TIMER(ti,oti, d4RdTimeout); rd = read(fd, buf+total, len-total); if (debugD4) { if (first_read) { fprintf(stderr, "read: "); first_read = 0; } if (rd < 0) { fprintf(stderr, "%i %s\n", rd, errno != 0 ?strerror(errno) : ""); first_read = 1; } else fprintf(stderr, "%i ", rd); } RESET_TIMER(ti,oti); if ( rd <= 0 ) { gettimeofday(&end, NULL); dt = (end.tv_sec - beg.tv_sec) * 1000; dt += (end.tv_usec - beg.tv_usec) / 1000; if ( dt > d4RdTimeout * 2 ) { if ( debugD4 ) fprintf(stderr,"Timeout 1 at readAnswer() rcv %d bytes\n",total); timeoutGot = 1; break; } count++; if ( count >= 100 ) { timeoutGot = 1; if ( rd == 0 ) errno = -1; /* tell that there is an abnormal condition */ break; } errno = 0; } else { total += rd; if ( total > 3 ) { /* the bytes idx 2 and 3 contain the length */ /* in case of errors this may differ from */ /* the expected lenght. Setting len to this */ /* value will avoid waiting for timeout */ len = (buf[2] << 8) + buf[3]; len = (len > sizeof(buf))?sizeof(buf) - 1:len; } } usleep(d4RdTimeout); } if ( debugD4 ) { # if PTIME gettimeofday(&end, NULL); # endif fprintf(stderr, "total: %i\n", total); printHexValues("Recv: ",buf,total); # if PTIME dt = (end.tv_sec - beg.tv_sec) * 1000000; dt += end.tv_usec - beg.tv_usec; fprintf(stderr,"Read time %5.3f s\n",(double)dt/1000000); # endif } if ( timeoutGot ) { if ( debugD4 ) fprintf(stderr,"Timeout 2 at readAnswer()\n"); return -1; } return total; }
static int writeCmd(int fd, unsigned char *cmd, int len) { int w; int i = 0; struct itimerval ti, oti; # if PTIME struct timeval beg, end; long dt; # endif if ( debugD4 ) { printCmdType(cmd); # if PTIME gettimeofday(&beg, NULL); # endif if ( cmd[0] == 0 && cmd[1] == 0 ) { printHexValues("Send: ", cmd, len); } else { printHexValues("Send: ", cmd, 6); } } usleep(1); /* according to Glen Steward, this will solve problems */ /* for the cartridge exchange with the Stylus Color 580 */ timeoutGot = 0; errno = 0; while ( i < len ) { SET_TIMER(ti,oti,d4WrTimeout); w = SafeWrite(fd, cmd+i,len-i); RESET_TIMER(ti,oti); if ( w < 0 ) { if ( debugD4 ) { perror("Write error"); } i= -1; break; } else i += w; } if ( debugD4 ) { # if PTIME gettimeofday(&end, NULL); dt = (end.tv_sec - beg.tv_sec) * 1000000; dt += end.tv_usec - beg.tv_usec; fprintf(stderr,"Write time %5.3f s\n",(double)dt/1000000); # endif } if ( timeoutGot ) return -1; return i; }
static int ps2cdvd_enter_leave(int state, int enter) { int res_state = state; switch (state) { case STAT_WAIT_DISC: if (enter) { if (ps2cdvd_state != STAT_CHECK_DISCTYPE) invalidate_discinfo(); ps2cdvd_lowlevel_unlock(); if (CURRENT) DPRINT(DBG_DIAG, "abort all pending request\n"); while (CURRENT) end_request(0); SET_TIMER(HZ * ps2cdvd_check_interval); } else { RESET_TIMER(); } break; case STAT_INIT_TRAYSTAT: if (enter) { if (ps2cdvd_send_trayreq(SCECdTrayCheck) < 0) { DPRINT(DBG_DIAG, "send_trayreq() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_CHECK_DISCTYPE: if (enter) { disc_type = INVALID_DISCTYPE; if (ps2cdvd_send_gettype() < 0) { DPRINT(DBG_DIAG, "send_gettype() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_INIT_CHECK_READY: if (enter) { //if (ps2cdvd_send_ready(1 /* non block */) < 0) { if (ps2cdvd_send_ready(0 /* block */) < 0) { DPRINT(DBG_DIAG, "send_ready() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_TOC_READ: if (enter) { if (ps2cdvd_send_gettoc(tocbuf, sizeof(tocbuf)) < 0) { DPRINT(DBG_DIAG, "send_gettoc() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_SET_MMODE: if (enter) { DPRINT(DBG_INFO, "media mode %s\n", media_mode == SCECdCD ? "CD" : "DVD"); if (ps2cdvd_send_mmode(media_mode) < 0) { DPRINT(DBG_DIAG, "send_mmode() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_LABEL_READ: if (enter) { if (ps2cdvd_send_read(16, 1, labelbuf, &DataMode) < 0) { DPRINT(DBG_DIAG, "send_read() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_LABEL_READ_ERROR_CHECK: if (enter) { if (ps2cdvd_send_geterror() < 0) { DPRINT(DBG_DIAG, "send_geterror() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_READY: if (enter) { ps2cdvd_lowlevel_unlock(); SET_TIMER(HZ * ps2cdvd_check_interval); } else { RESET_TIMER(); } break; case STAT_CHECK_TRAY: if (enter) { if (ps2cdvd_send_trayreq(2) < 0) { DPRINT(DBG_DIAG, "send_trayreq() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_READ: if (enter) { DPRINT(DBG_READ, "REQ %p: sec=%ld n=%ld buf=%p\n", CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->buffer); if (ps2cdvd_send_read(CURRENT->sector/4, ps2cdvd_databuf_size, ps2cdvd_databuf, &DataMode) < 0) { DPRINT(DBG_DIAG, "send_readdata() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } else { ps2cdvd_databuf_addr = CURRENT->sector/4; } } else { } break; case STAT_READ_EOM_RETRY: if (enter) { DPRINT(DBG_READ, "REQ %p: sec=%ld n=%ld buf=%p (EOM retry)\n", CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->buffer); if (ps2cdvd_send_read(CURRENT->sector/4 - ps2cdvd_databuf_size + 1, ps2cdvd_databuf_size, ps2cdvd_databuf, &DataMode) < 0) { DPRINT(DBG_DIAG, "send_readdata() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } else { ps2cdvd_databuf_addr = CURRENT->sector/4 - ps2cdvd_databuf_size + 1; } } else { } break; case STAT_READ_ERROR_CHECK: if (enter) { if (ps2cdvd_send_geterror() < 0) { DPRINT(DBG_DIAG, "send_geterror() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_INVALID_DISC: if (enter) { if (!disc_locked) { DPRINT(DBG_DIAG, "attempt to enter INVALID_DISC state while !disc_locked\n"); res_state = ps2cdvd_enter(STAT_WAIT_DISC); } else { invalidate_discinfo(); ps2cdvd_lowlevel_unlock(); SET_TIMER(HZ * ps2cdvd_check_interval); } } else { RESET_TIMER(); } break; case STAT_SPINDOWN: if (enter) { if (ps2cdvd_send_stop() < 0) { DPRINT(DBG_DIAG, "send_stop() failed\n"); res_state = ps2cdvd_enter(STAT_ERROR); } } else { } break; case STAT_IDLE: if (enter) { invalidate_discinfo(); ps2cdvd_lowlevel_unlock(); } else { RESET_TIMER(); } break; case STAT_ERROR: if (enter) { invalidate_discinfo(); while (CURRENT) end_request(0); ps2cdvd_lowlevel_unlock(); } else { } break; default: printk(KERN_CRIT "ps2cdvd: INVALID STATE\n"); break; } return res_state; }
static void ps2cdvd_state_machine(struct ps2cdvd_event* ev) { unsigned long flags; int old_state = ps2cdvd_state; int new_state = ps2cdvd_state; struct sbr_common_arg *carg = ev->arg; DPRINT(DBG_STATE, "state: %s event: %s\n", ps2cdvd_getstatestr(old_state), ps2cdvd_geteventstr(ev->type)); save_flags(flags); cli(); switch (ps2cdvd_state) { case STAT_WAIT_DISC: switch (ev->type) { case EV_START: case EV_TIMEOUT: if (ps2cdvd_lowlevel_lock() < 0) { /* waiting for unlock... */ RESET_TIMER(); SET_TIMER(HZ * ps2cdvd_check_interval); } else { new_state = STAT_INIT_TRAYSTAT; } break; case EV_INTR: } break; case STAT_INIT_TRAYSTAT: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: { if (carg->result != 0) { new_state = STAT_WAIT_DISC; } else { new_state = STAT_CHECK_DISCTYPE; } } break; } break; case STAT_CHECK_DISCTYPE: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: disc_type = carg->result; DPRINT(DBG_INFO, "ps2cdvd_getdisctype()='%s', %d\n", ps2cdvd_getdisctypestr(disc_type), disc_type); switch (disc_type) { case SCECdPS2CDDA: /* PS2 CD DA */ case SCECdPS2CD: /* PS2 CD */ case SCECdPSCDDA: /* PS CD DA */ case SCECdPSCD: /* PS CD */ case SCECdCDDA: /* CD DA */ case SCECdPS2DVD: /* PS2 DVD */ case SCECdDVDV: /* DVD video */ new_state = STAT_INIT_CHECK_READY; break; case SCECdDETCTDVDD: /* DVD-dual detecting */ case SCECdDETCTDVDS: /* DVD-single detecting */ case SCECdDETCTCD: /* CD detecting */ case SCECdDETCT: /* detecting */ case SCECdNODISC: /* no disc */ new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC; break; case SCECdIllgalMedia: /* illegal media */ case SCECdUNKNOWN: /* unknown */ printk(KERN_CRIT "ps2cdvd: illegal media\n"); new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC; break; } break; } break; case STAT_INIT_CHECK_READY: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: prev_read = jiffies; if (carg->result == SCECdComplete) { switch (disc_type) { case SCECdPS2CDDA: /* PS2 CD DA */ case SCECdPS2CD: /* PS2 CD */ case SCECdPSCDDA: /* PS CD DA */ case SCECdPSCD: /* PS CD */ case SCECdCDDA: /* CD DA */ new_state = STAT_TOC_READ; media_mode = SCECdCD; break; case SCECdPS2DVD: /* PS2 DVD */ case SCECdDVDV: /* DVD video */ new_state = STAT_SET_MMODE; media_mode = SCECdDVD; break; default: printk(KERN_CRIT "ps2cdvd: internal error at %s(%d)\n", __FILE__, __LINE__); new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC; break; } } else { new_state = STAT_WAIT_DISC; } break; } break; case STAT_TOC_READ: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: if (carg->result < 0) { DPRINT(DBG_DIAG, "gettoc() failed\n"); new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC; } else { struct ps2cdvd_tocentry *toc; toc_valid = 1; toc = (struct ps2cdvd_tocentry *)tocbuf; leadout_start = msftolba(decode_bcd(toc[2].abs_msf[0]), decode_bcd(toc[2].abs_msf[1]), decode_bcd(toc[2].abs_msf[2])); #ifdef PS2CDVD_DEBUG if (ps2cdvd_debug & DBG_INFO) { struct sbr_cdvd_gettoc_arg *arg = carg->arg; if (arg->media == 0) { ps2cdvd_tocdump(DBG_LOG_LEVEL "ps2cdvd: ", (struct ps2cdvd_tocentry *)tocbuf); } else { /* * we have no interrest in DVD Physical format information ps2cdvd_hexdump(tocbuf, len); */ } } #endif new_state = STAT_SET_MMODE; } break; } break; case STAT_SET_MMODE: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: if (carg->result == 0) { DPRINT(DBG_DIAG, "set_mmode() failed\n"); new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC; } else { switch (disc_type) { case SCECdPS2DVD: /* PS2 DVD */ case SCECdPS2CDDA: /* PS2 CD DA */ case SCECdPS2CD: /* PS2 CD */ case SCECdPSCDDA: /* PS CD DA */ case SCECdPSCD: /* PS CD */ new_state = STAT_LABEL_READ; break; case SCECdDVDV: /* DVD video */ case SCECdCDDA: /* CD DA */ if (disc_locked && disc_lock_key_valid) { new_state = STAT_LABEL_READ; } else { disc_changed++; new_state = STAT_READY; } break; default: printk(KERN_CRIT "ps2cdvd: internal error at %s(%d)\n", __FILE__, __LINE__); new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC; break; } break; } } break; case STAT_LABEL_READ: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: new_state = STAT_LABEL_READ_ERROR_CHECK; break; } break; case STAT_LABEL_READ_ERROR_CHECK: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: if (carg->result != SCECdErNO) { DPRINT(DBG_DIAG, "error: %s, code=0x%02x\n", ps2cdvd_geterrorstr(carg->result), carg->result); if (disc_locked && disc_lock_key_valid) { printk(KERN_CRIT "ps2cdvd: =============================\n"); printk(KERN_CRIT "ps2cdvd: wrong disc. \n"); printk(KERN_CRIT "ps2cdvd: =============================\n"); if (!ps2cdvd_wrong_disc_retry) { INIT_REQUEST; while (CURRENT) end_request(0); disc_changed++; } } new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC; } else { unsigned long sum; #ifdef PS2CDVD_DEBUG struct iso_primary_descriptor *label; label = (struct iso_primary_descriptor*)labelbuf; if (ps2cdvd_debug & DBG_INFO) { printk(DBG_LOG_LEVEL "ps2cdvd: "); print_isofsstr(label->system_id, sizeof(label->system_id)); print_isofsstr(label->volume_id, sizeof(label->volume_id)); print_isofsstr(label->volume_set_id, sizeof(label->volume_set_id)); print_isofsstr(label->publisher_id, sizeof(label->publisher_id)); print_isofsstr(label->application_id, sizeof(label->application_id)); printk("\n"); /* ps2cdvd_hexdump(DBG_LOG_LEVEL "ps2cdvd: ", labelbuf, 2048); */ } #endif label_valid = 1; DPRINT(DBG_DLOCK, "label is valid\n"); sum = checksum((u_long*)labelbuf, 2048/sizeof(u_long)); if (disc_lock_key_valid && disc_locked && disc_lock_key != sum) { printk(KERN_CRIT "ps2cdvd: =============================\n"); printk(KERN_CRIT "ps2cdvd: wrong disc. \n"); printk(KERN_CRIT "ps2cdvd: =============================\n"); if (!ps2cdvd_wrong_disc_retry) { INIT_REQUEST; while (CURRENT) end_request(0); disc_changed++; } new_state = STAT_INVALID_DISC; } else { disc_lock_key = sum; if (!disc_lock_key_valid && disc_locked) { DPRINT(DBG_DLOCK, "disc lock key=%lX\n", sum); } disc_lock_key_valid = 1; new_state = STAT_READY; } } break; } break; case STAT_READY: switch (ev->type) { case EV_TICK: if (CURRENT == NULL || ps2sif_iswaiting(ps2cdvd_lock)) { break; } /* fall through */ case EV_START: case EV_TIMEOUT: if (ps2cdvd_lowlevel_lock() < 0) { /* waiting for unlock... */ RESET_TIMER(); SET_TIMER(HZ * ps2cdvd_check_interval); break; } if (CURRENT == NULL) { if (ps2cdvd_spindown * HZ < jiffies - prev_read) { new_state = STAT_SPINDOWN; } else { /* nothing to do */ ps2cdvd_lowlevel_unlock(); RESET_TIMER(); SET_TIMER(HZ * ps2cdvd_check_interval); } } else { prev_read = jiffies; if (jiffies - prev_tray_check < HZ/2) { new_state = STAT_READ; } else { prev_tray_check = jiffies; new_state = STAT_CHECK_TRAY; } } break; case EV_INTR: break; } break; case STAT_CHECK_TRAY: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: if (carg->result < 0) { new_state = STAT_ERROR; } else { struct sbr_cdvd_trayreq_arg *arg = carg->arg; if (arg->traycount != 0) { if (disc_locked) { printk(KERN_CRIT"ps2cdvd: =============================\n"); printk(KERN_CRIT"ps2cdvd: the disc is currently locked.\n"); printk(KERN_CRIT"ps2cdvd: please don't take it away!\n"); printk(KERN_CRIT"ps2cdvd: =============================\n"); } invalidate_discinfo(); new_state = STAT_CHECK_DISCTYPE; } else { if (CURRENT) { new_state = STAT_READ; } else { new_state = STAT_READY; } } } break; } break; case STAT_READ: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: new_state = STAT_READ_ERROR_CHECK; break; } break; case STAT_READ_EOM_RETRY: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: new_state = STAT_READ_ERROR_CHECK; break; } break; case STAT_READ_ERROR_CHECK: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: if (carg->result == SCECdErNO) { /* * succeeded */ while (CURRENT != NULL && ps2cdvd_databuf_addr <= CURRENT->sector/4 && CURRENT->sector/4 < ps2cdvd_databuf_addr + ps2cdvd_databuf_size) { memcpy(CURRENT->buffer, ps2cdvd_databuf + DATA_SECT_SIZE * (CURRENT->sector/4 - ps2cdvd_databuf_addr), DATA_SECT_SIZE); end_request(1); } if (!ps2sif_iswaiting(ps2cdvd_lock) && CURRENT != NULL) { /* tiny acceleration */ new_state = STAT_READ; } else { new_state = STAT_READY; } } else if (carg->result == 0x38) { /* * sector format error */ DPRINT(DBG_DIAG, "error: sector format error, code=0x38 (ignored)\n"); memset(CURRENT->buffer, 0, DATA_SECT_SIZE); end_request(1); if (!ps2sif_iswaiting(ps2cdvd_lock) && CURRENT != NULL) { /* tiny acceleration */ new_state = STAT_READ; } else { new_state = STAT_READY; } } else if (carg->result == SCECdErEOM && ps2cdvd_databuf_addr != CURRENT->sector/4 - ps2cdvd_databuf_size + 1 && ps2cdvd_databuf_size <= CURRENT->sector/4) { /* you got End Of Media and you have not retried */ DPRINT(DBG_DIAG, "error: %s, code=0x%02x (retry...)\n", ps2cdvd_geterrorstr(carg->result), carg->result); new_state = STAT_READ_EOM_RETRY; } else { DPRINT(DBG_DIAG, "error: %s, code=0x%02x\n", ps2cdvd_geterrorstr(carg->result), carg->result); ps2cdvd_databuf_addr = -1; end_request(0); /* I/O error */ new_state = STAT_READY; } break; } break; case STAT_INVALID_DISC: switch (ev->type) { case EV_START: case EV_TIMEOUT: if (ps2cdvd_lowlevel_lock() < 0) { /* waiting for unlock... */ RESET_TIMER(); SET_TIMER(HZ * ps2cdvd_check_interval); } else { new_state = STAT_CHECK_DISCTYPE; } break; case EV_INTR: break; } break; case STAT_SPINDOWN: switch (ev->type) { case EV_START: case EV_TIMEOUT: break; case EV_INTR: if (CURRENT == NULL) { new_state = STAT_IDLE; } else { DPRINT(DBG_VERBOSE, "re-spinup...\n"); new_state = STAT_CHECK_DISCTYPE; } break; } break; case STAT_IDLE: switch (ev->type) { case EV_START: case EV_TIMEOUT: if (ps2cdvd_lowlevel_lock() < 0) { /* waiting for unlock... */ RESET_TIMER(); SET_TIMER(HZ * ps2cdvd_check_interval); } else { new_state = STAT_CHECK_DISCTYPE; } break; case EV_INTR: break; } break; case STAT_ERROR: break; default: printk(KERN_ERR "ps2cdvd: invalid state"); ps2cdvd_state = STAT_WAIT_DISC; break; } if (new_state != old_state) { struct ps2cdvd_event tick; tick.type = EV_TICK; ps2cdvd_leave(old_state); ps2cdvd_state = ps2cdvd_enter(new_state); DPRINT(DBG_STATE, " -> new state: %s\n", ps2cdvd_getstatestr(ps2cdvd_state)); if (old_state != ps2cdvd_state && ps2cdvd_state == STAT_READY) { ps2cdvd_state_machine(&tick); } wake_up_interruptible(&statq); } restore_flags(flags); } __initfunc(int ps2cdvd_init(void)) { int res; DPRINT(DBG_VERBOSE, "init: get lock\n"); if ((ps2cdvd_lock = ps2sif_getlock(PS2LOCK_CDVD)) == NULL) { printk(KERN_ERR "ps2cdvd: Can't get lock\n"); ps2cdvd_cleanup(); return -EINVAL; } ps2sif_lockqueueinit(&ps2cdvd_lock_qi); ps2cdvd_lock_qi.name = "ps2cdvd"; DPRINT(DBG_VERBOSE, "init: initialize timer\n"); init_timer(&io_timer); io_timer.function = (void(*)(u_long))ps2cdvd_timer; ps2cdvd_state = STAT_WAIT_DISC; DPRINT(DBG_VERBOSE, "init: allocate diaklabel buffer\n"); labelbuf = kmalloc(2048, GFP_KERNEL); if (labelbuf == NULL) { printk(KERN_ERR "ps2cdvd: Can't allocate buffer\n"); ps2cdvd_cleanup(); return -ENOMEM; } initialized |= INIT_LABELBUF; DPRINT(DBG_VERBOSE, "allocate buffer\n"); ps2cdvd_databufx = kmalloc(ps2cdvd_databuf_size * AUDIO_SECT_SIZE + BUFFER_ALIGNMENT, GFP_KERNEL); if (ps2cdvd_databufx == NULL) { printk(KERN_ERR "ps2cdvd: Can't allocate buffer\n"); ps2cdvd_cleanup(); return -ENOMEM; } ps2cdvd_databuf = ALIGN(ps2cdvd_databufx, BUFFER_ALIGNMENT); initialized |= INIT_DATABUF; DPRINT(DBG_VERBOSE, "init: call sbios\n"); if (ps2cdvdcall_init()) { printk(KERN_ERR "ps2cdvd: Can't initialize CD/DVD-ROM subsystem\n"); ps2cdvd_cleanup(); return -EIO; } #ifdef CONFIG_PS2_SBIOS_VER_CHECK if (0x0201 <= sbios(SB_GETVER, NULL)) ps2cdvdcall_reset(); #else ps2cdvdcall_reset(); #endif initialized |= INIT_IOPSIDE; DPRINT(DBG_VERBOSE, "init: register block device\n"); if ((res = register_blkdev(MAJOR_NR, "ps2cdvd", &cdrom_fops)) < 0) { printk(KERN_ERR "ps2cdvd: Unable to get major %d for PS2 CD/DVD-ROM\n", MAJOR_NR); ps2cdvd_cleanup(); return -EIO; } if (MAJOR_NR == 0) MAJOR_NR = res; initialized |= INIT_BLKDEV; blksize_size[MAJOR_NR] = ps2cdvd_blocksizes; hardsect_size[MAJOR_NR] = ps2cdvd_hardsectsizes; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = ps2cdvd_read_ahead; DPRINT(DBG_VERBOSE, "init: register cdrom\n"); ps2cdvd_info.dev = MKDEV(MAJOR_NR, 0); if (register_cdrom(&ps2cdvd_info) != 0) { printk(KERN_ERR "ps2cdvd: Cannot register PS2 CD/DVD-ROM\n"); ps2cdvd_cleanup(); return -EIO; } initialized |= INIT_CDROM; printk(KERN_INFO "PS2 CD/DVD-ROM driver\n"); if (ps2cdvd_lowlevel_lock() == 0) ps2cdvd_state = ps2cdvd_enter(STAT_INIT_TRAYSTAT); else ps2cdvd_state = ps2cdvd_enter(STAT_WAIT_DISC); return 0; }
static void mcd_poll(void) { int st; if (mcd_error) { if (mcd_error & 0xA5) { printk("mcd: I/O error 0x%02x", mcd_error); if (mcd_error & 0x80) printk(" (Door open)"); if (mcd_error & 0x20) printk(" (Disk changed)"); if (mcd_error & 0x04) { printk(" (Read error)"); /* Bitch about the problem. */ /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */ /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */ /* But I find that rather HANDY!!! */ /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */ /* AJK [06/17/95] */ /* Slap the CD down to single speed! */ if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_2X_READ) { MCMD_DATA_READ = MCMD_PLAY_READ; /* Uhhh, Ummmm, muhuh-huh! */ mcd1xhold = SINGLE_HOLD_SECTORS; /* Hey Beavis! */ printk(" Speed now 1x"); /* Pull my finger! */ } } printk("\n"); mcd_invalidate_buffers(); #ifdef WARN_IF_READ_FAILURE if (McdTries == MCD_RETRY_ATTEMPTS) printk("mcd: read of block %d failed\n", mcd_next_bn); #endif if (!McdTries--) { /* Nuts! This cd is ready for recycling! */ /* When WAS the last time YOU cleaned it CORRECTLY?! */ printk("mcd: read of block %d failed, giving up\n", mcd_next_bn); if (mcd_transfer_is_active) { McdTries = 0; goto ret; } if (CURRENT_VALID) end_request(0); McdTries = MCD_RETRY_ATTEMPTS; } } mcd_error = 0; mcd_state = MCD_S_STOP; } /* Switch back to Double speed if enough GOOD sectors were read! */ /* Are we a double speed with a crappy CD?! */ if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_PLAY_READ) { /* We ARE a double speed and we ARE bitching! */ if (mcd1xhold == 0) /* Okay, Like are we STILL at single speed? */ { /* We need to switch back to double speed now... */ MCMD_DATA_READ = MCMD_2X_READ; /* Uhhh... BACK You GO! */ printk("mcd: Switching back to 2X speed!\n"); /* Tell 'em! */ } else mcd1xhold--; /* No?! Count down the good reads some more... */ /* and try, try again! */ } immediately: switch (mcd_state) { case MCD_S_IDLE: #ifdef TEST3 printk("MCD_S_IDLE\n"); #endif return; case MCD_S_START: #ifdef TEST3 printk("MCD_S_START\n"); #endif outb(MCMD_GET_STATUS, MCDPORT(0)); mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE; McdTimeout = 3000; break; case MCD_S_MODE: #ifdef TEST3 printk("MCD_S_MODE\n"); #endif if ((st = mcdStatus()) != -1) { if (st & MST_DSK_CHG) { mcdDiskChanged = 1; tocUpToDate = 0; mcd_invalidate_buffers(); } set_mode_immediately: if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) { mcdDiskChanged = 1; tocUpToDate = 0; if (mcd_transfer_is_active) { mcd_state = MCD_S_START; goto immediately; } printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n"); mcd_state = MCD_S_IDLE; while (CURRENT_VALID) end_request(0); return; } outb(MCMD_SET_MODE, MCDPORT(0)); outb(1, MCDPORT(0)); mcd_mode = 1; mcd_state = MCD_S_READ; McdTimeout = 3000; } break; case MCD_S_READ: #ifdef TEST3 printk("MCD_S_READ\n"); #endif if ((st = mcdStatus()) != -1) { if (st & MST_DSK_CHG) { mcdDiskChanged = 1; tocUpToDate = 0; mcd_invalidate_buffers(); } read_immediately: if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) { mcdDiskChanged = 1; tocUpToDate = 0; if (mcd_transfer_is_active) { mcd_state = MCD_S_START; goto immediately; } printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n"); mcd_state = MCD_S_IDLE; while (CURRENT_VALID) end_request(0); return; } if (CURRENT_VALID) { struct mcd_Play_msf msf; mcd_next_bn = CURRENT -> sector / 4; hsg2msf(mcd_next_bn, &msf.start); msf.end.min = ~0; msf.end.sec = ~0; msf.end.frame = ~0; sendMcdCmd(MCMD_DATA_READ, &msf); mcd_state = MCD_S_DATA; McdTimeout = READ_TIMEOUT; } else { mcd_state = MCD_S_STOP; goto immediately; } } break; case MCD_S_DATA: #ifdef TEST3 printk("MCD_S_DATA\n"); #endif st = inb(MCDPORT(1)) & (MFL_STATUSorDATA); data_immediately: #ifdef TEST5 printk("Status %02x\n",st); #endif switch (st) { case MFL_DATA: #ifdef WARN_IF_READ_FAILURE if (McdTries == 5) printk("mcd: read of block %d failed\n", mcd_next_bn); #endif if (!McdTries--) { printk("mcd: read of block %d failed, giving up\n", mcd_next_bn); if (mcd_transfer_is_active) { McdTries = 0; break; } if (CURRENT_VALID) end_request(0); McdTries = 5; } mcd_state = MCD_S_START; McdTimeout = READ_TIMEOUT; goto immediately; case MFL_STATUSorDATA: break; default: McdTries = 5; if (!CURRENT_VALID && mcd_buf_in == mcd_buf_out) { mcd_state = MCD_S_STOP; goto immediately; } mcd_buf_bn[mcd_buf_in] = -1; READ_DATA(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in, 2048); mcd_buf_bn[mcd_buf_in] = mcd_next_bn++; if (mcd_buf_out == -1) mcd_buf_out = mcd_buf_in; mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1; if (!mcd_transfer_is_active) { while (CURRENT_VALID) { mcd_transfer(); if (CURRENT -> nr_sectors == 0) end_request(1); else break; } } if (CURRENT_VALID && (CURRENT -> sector / 4 < mcd_next_bn || CURRENT -> sector / 4 > mcd_next_bn + 16)) { mcd_state = MCD_S_STOP; goto immediately; } McdTimeout = READ_TIMEOUT; #ifdef DOUBLE_QUICK_ONLY if (MCMD_DATA_READ != MCMD_PLAY_READ) #endif { int count= QUICK_LOOP_COUNT; while (count--) { QUICK_LOOP_DELAY; if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) { # ifdef TEST4 /* printk("Quickloop success at %d\n",QUICK_LOOP_COUNT-count); */ printk(" %d ",QUICK_LOOP_COUNT-count); # endif goto data_immediately; } } # ifdef TEST4 /* printk("Quickloop ended at %d\n",QUICK_LOOP_COUNT); */ printk("ended "); # endif } break; } break; case MCD_S_STOP: #ifdef TEST3 printk("MCD_S_STOP\n"); #endif #ifdef WORK_AROUND_MITSUMI_BUG_93 if (!mitsumi_bug_93_wait) goto do_not_work_around_mitsumi_bug_93_1; McdTimeout = mitsumi_bug_93_wait; mcd_state = 9+3+1; break; case 9+3+1: if (McdTimeout) break; do_not_work_around_mitsumi_bug_93_1: #endif /* WORK_AROUND_MITSUMI_BUG_93 */ outb(MCMD_STOP, MCDPORT(0)); #ifdef WORK_AROUND_MITSUMI_BUG_92 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) { int i = 4096; do { inb(MCDPORT(0)); } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i); outb(MCMD_STOP, MCDPORT(0)); if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) { i = 4096; do { inb(MCDPORT(0)); } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i); outb(MCMD_STOP, MCDPORT(0)); } } #endif /* WORK_AROUND_MITSUMI_BUG_92 */ mcd_state = MCD_S_STOPPING; McdTimeout = 1000; break; case MCD_S_STOPPING: #ifdef TEST3 printk("MCD_S_STOPPING\n"); #endif if ((st = mcdStatus()) == -1 && McdTimeout) break; if ((st != -1) && (st & MST_DSK_CHG)) { mcdDiskChanged = 1; tocUpToDate = 0; mcd_invalidate_buffers(); } #ifdef WORK_AROUND_MITSUMI_BUG_93 if (!mitsumi_bug_93_wait) goto do_not_work_around_mitsumi_bug_93_2; McdTimeout = mitsumi_bug_93_wait; mcd_state = 9+3+2; break; case 9+3+2: if (McdTimeout) break; st = -1; do_not_work_around_mitsumi_bug_93_2: #endif /* WORK_AROUND_MITSUMI_BUG_93 */ #ifdef TEST3 printk("CURRENT_VALID %d mcd_mode %d\n", CURRENT_VALID, mcd_mode); #endif if (CURRENT_VALID) { if (st != -1) { if (mcd_mode == 1) goto read_immediately; else goto set_mode_immediately; } else { mcd_state = MCD_S_START; McdTimeout = 1; } } else { mcd_state = MCD_S_IDLE; return; } break; default: printk("mcd: invalid state %d\n", mcd_state); return; } ret: if (!McdTimeout--) { printk("mcd: timeout in state %d\n", mcd_state); mcd_state = MCD_S_STOP; } SET_TIMER(mcd_poll, 1); }
/* * TODO: when cache miss, check the iif, because probably ASSERTS * shoult take place */ static void process_cache_miss(struct igmpmsg *igmpctl) { u_int32 source, mfc_source; u_int32 group; u_int32 rp_addr; vifi_t iif; mrtentry_t *mrtentry_ptr; mrtentry_t *mrtentry_rp; /* * When there is a cache miss, we check only the header of the packet * (and only it should be sent up by the kernel. */ group = igmpctl->im_dst.s_addr; source = mfc_source = igmpctl->im_src.s_addr; iif = igmpctl->im_vif; IF_DEBUG(DEBUG_MFC) logit(LOG_DEBUG, 0, "Cache miss, src %s, dst %s, iif %d", inet_fmt(source, s1, sizeof(s1)), inet_fmt(group, s2, sizeof(s2)), iif); /* TODO: XXX: check whether the kernel generates cache miss for the * LAN scoped addresses */ if (ntohl(group) <= INADDR_MAX_LOCAL_GROUP) return; /* Don't create routing entries for the LAN scoped addresses */ /* TODO: check if correct in case the source is one of my addresses */ /* If I am the DR for this source, create (S,G) and add the register_vif * to the oifs. */ if ((uvifs[iif].uv_flags & VIFF_DR) && (find_vif_direct_local(source) == iif)) { mrtentry_ptr = find_route(source, group, MRTF_SG, CREATE); if (mrtentry_ptr == (mrtentry_t *)NULL) return; mrtentry_ptr->flags &= ~MRTF_NEW; /* set reg_vif_num as outgoing interface ONLY if I am not the RP */ if (mrtentry_ptr->group->rpaddr != my_cand_rp_address) VIFM_SET(reg_vif_num, mrtentry_ptr->joined_oifs); change_interfaces(mrtentry_ptr, mrtentry_ptr->incoming, mrtentry_ptr->joined_oifs, mrtentry_ptr->pruned_oifs, mrtentry_ptr->leaves, mrtentry_ptr->asserted_oifs, 0); } else { mrtentry_ptr = find_route(source, group, MRTF_SG | MRTF_WC | MRTF_PMBR, DONT_CREATE); if (mrtentry_ptr == (mrtentry_t *)NULL) return; } /* TODO: if there are too many cache miss for the same (S,G), install * negative cache entry in the kernel (oif==NULL) to prevent too * many upcalls. */ if (mrtentry_ptr->incoming == iif) { if (!VIFM_ISEMPTY(mrtentry_ptr->oifs)) { if (mrtentry_ptr->flags & MRTF_SG) { /* TODO: check that the RPbit is not set? */ /* TODO: XXX: TIMER implem. dependency! */ if (mrtentry_ptr->timer < PIM_DATA_TIMEOUT) SET_TIMER(mrtentry_ptr->timer, PIM_DATA_TIMEOUT); if (!(mrtentry_ptr->flags & MRTF_SPT)) { if ((mrtentry_rp = mrtentry_ptr->group->grp_route) == (mrtentry_t *)NULL) mrtentry_rp = mrtentry_ptr->group->active_rp_grp->rp->rpentry->mrtlink; if (mrtentry_rp != (mrtentry_t *)NULL) { /* Check if the (S,G) iif is different from * the (*,G) or (*,*,RP) iif */ if ((mrtentry_ptr->incoming != mrtentry_rp->incoming) || (mrtentry_ptr->upstream != mrtentry_rp->upstream)) { mrtentry_ptr->flags |= MRTF_SPT; mrtentry_ptr->flags &= ~MRTF_RP; } } } } if (mrtentry_ptr->flags & MRTF_PMBR) rp_addr = mrtentry_ptr->source->address; else rp_addr = mrtentry_ptr->group->rpaddr; mfc_source = source; #ifdef KERNEL_MFC_WC_G if (mrtentry_ptr->flags & (MRTF_WC | MRTF_PMBR)) if (!(mrtentry_ptr->flags & MRTF_MFC_CLONE_SG)) mfc_source = INADDR_ANY_N; #endif /* KERNEL_MFC_WC_G */ add_kernel_cache(mrtentry_ptr, mfc_source, group, MFC_MOVE_FORCE); #ifdef SCOPED_ACL APPLY_SCOPE(group,mrtentry_ptr); #endif k_chg_mfc(igmp_socket, mfc_source, group, iif, mrtentry_ptr->oifs, rp_addr); /* TODO: XXX: No need for RSRR message, because nothing has * changed. */ } return; /* iif match */ } /* The iif doesn't match */ if (mrtentry_ptr->flags & MRTF_SG) { if (mrtentry_ptr->flags & MRTF_SPT) /* Arrived on wrong interface */ return; if ((mrtentry_rp = mrtentry_ptr->group->grp_route) == (mrtentry_t *)NULL) mrtentry_rp = mrtentry_ptr->group->active_rp_grp->rp->rpentry->mrtlink; if (mrtentry_rp != (mrtentry_t *)NULL) { if (mrtentry_rp->incoming == iif) { /* Forward on (*,G) or (*,*,RP) */ #ifdef KERNEL_MFC_WC_G if (!(mrtentry_rp->flags & MRTF_MFC_CLONE_SG)) mfc_source = INADDR_ANY_N; #endif /* KERNEL_MFC_WC_G */ add_kernel_cache(mrtentry_rp, mfc_source, group, 0); /* marian: not sure if we are going to reach here for our scoped traffic */ #ifdef SCOPED_ACL APPLY_SCOPE(group,mrtentry_ptr); #endif k_chg_mfc(igmp_socket, mfc_source, group, iif, mrtentry_rp->oifs, mrtentry_ptr->group->rpaddr); #ifdef RSRR rsrr_cache_send(mrtentry_rp, RSRR_NOTIFICATION_OK); #endif /* RSRR */ } } return; } }