static void disk_setstatus(struct disk_data *dd, uint32_t val) { switch (val) { case DISKSTAT_IDLE: HWTRACE(DOTRACE_DISK, "disk: slot %d: idle", dd->dd_slot); dd->dd_iostatus = -1; break; case DISKSTAT_READING: HWTRACE(DOTRACE_DISK, "disk: slot %d: read starts", dd->dd_slot); dd->dd_iostatus = 0; break; case DISKSTAT_WRITING: HWTRACE(DOTRACE_DISK, "disk: slot %d: write starts", dd->dd_slot); if (dd->dd_usedoom) { doom_tick(); } dd->dd_iostatus = 0; break; default: hang("disk: Invalid write %u to status register", val); return; } dd->dd_stat = val; disk_update(dd); }
static void keepalive(void *data, u_int32_t junk) { struct linkheader lh; struct net_data *nd = data; int r; (void)junk; /* * Because we're using a connectionless socket, the hub won't * know we exist until we send it a packet. So let's send it a * packet. In fact, let's do this say once a second all along * in case the hub crashes and restarts. */ lh.lh_frame = htons(FRAME_MAGIC); lh.lh_from = htons(nd->nd_status & NDS_HWADDR); lh.lh_packetlen = htons(sizeof(lh)); lh.lh_to = htons(HUB_ADDR); r = sendto(nd->nd_socket, (void *)&lh, sizeof(lh), 0, (struct sockaddr *)&nd->nd_hubaddr, nd->nd_hubaddrlen); if (r<0 && (errno==ECONNREFUSED || errno==ENOENT || errno==ENOTSOCK)) { /* * No carrier. */ if (!nd->nd_lostcarrier) { msg("nic: slot %d: lost carrier", nd->nd_slot); nd->nd_lostcarrier = 1; } HWTRACE(DOTRACE_NET, "nic: slot %d: keepalive rejected: %s", nd->nd_slot, strerror(errno)); } else if (r<0) { msg("nic: slot %d: keepalive to %s failed: %s", nd->nd_slot, nd->nd_hubaddr.sun_path, strerror(errno)); HWTRACE(DOTRACE_NET, "nic: slot %d: keepalive failed", nd->nd_slot); } else { if (nd->nd_lostcarrier) { msg("nic: slot %d: carrier detected", nd->nd_slot); nd->nd_lostcarrier = 0; } HWTRACE(DOTRACE_NET, "nic: slot %d: keepalive succeeded", nd->nd_slot); } schedule_event(1000000000, nd, 0, keepalive, "net keepalive"); }
void lower_irq(int slot) { bus_raised_interrupts &= ~((uint32_t)1 << slot); irqupdate(); HWTRACE(DOTRACE_IRQ, "Slot %2d: irq OFF", (slot)); }
void raise_irq(int slot) { bus_raised_interrupts |= ((uint32_t)1 << slot); irqupdate(); HWTRACE(DOTRACE_IRQ, "Slot %2d: irq ON", (slot)); }
static void dosend(struct net_data *nd) { struct linkheader *lh = (struct linkheader *)nd->nd_wbuf; u_int32_t len; int r; len = ntohs(lh->lh_packetlen); if (len > NET_BUFSIZE) { hang("Packet size too long"); return; } HWTRACE(DOTRACE_NET, "nic: slot %d: starting send (%u bytes)", nd->nd_slot, len); /* * Force the link-level header to the right values */ lh->lh_frame = htons(FRAME_MAGIC); lh->lh_from = htons(nd->nd_status & NDS_HWADDR); r = sendto(nd->nd_socket, nd->nd_wbuf, len, 0, (struct sockaddr *)&nd->nd_hubaddr, nd->nd_hubaddrlen); if (r<0) { msg("nic: slot %d: sendto: %s", nd->nd_slot, strerror(errno)); } g_stats.s_wpkts++; writedone(nd); }
static void readdone(struct net_data *nd) { HWTRACE(DOTRACE_NET, "nic: slot %d: packet received", nd->nd_slot); nd->nd_rirq = NDI_DONE; chkint(nd); }
static void writedone(struct net_data *nd) { HWTRACE(DOTRACE_NET, "nic: slot %d: packet sent", nd->nd_slot); nd->nd_wirq = NDI_DONE; chkint(nd); }
static int dorecv(void *data) { struct net_data *nd = data; char junk[8]; char *readbuf; size_t readbuflen; struct linkheader *lh; int overrun=0, r; if (nd->nd_rirq != 0) { /* * The last packet we got hasn't cleared yet. * Drop this one. */ overrun = 1; readbuf = junk; readbuflen = sizeof(junk); } else { readbuf = nd->nd_rbuf; readbuflen = NET_BUFSIZE; } r = read(nd->nd_socket, readbuf, readbuflen); if (r<0) { msg("nic: slot %d: read: %s", nd->nd_slot, strerror(errno)); HWTRACE(DOTRACE_NET, "nic: slot %d: read error", nd->nd_slot); return 0; } if (r < 8) { HWTRACE(DOTRACE_NET, "nic: slot %d: runt packet", nd->nd_slot); g_stats.s_epkts++; return 0; } lh = (struct linkheader *)readbuf; if (ntohs(lh->lh_frame) != FRAME_MAGIC) { HWTRACE(DOTRACE_NET, "nic: slot %d: framing error", nd->nd_slot); g_stats.s_epkts++; return 0; } if (ntohs(lh->lh_to) != (u_int16_t)(nd->nd_status & NDS_HWADDR) && ntohs(lh->lh_to) != BROADCAST_ADDR && (nd->nd_control & NDC_PROMISC)==0) { HWTRACE(DOTRACE_NET, "nic: slot %d: packet not for us", nd->nd_slot); return 0; } if (ntohs(lh->lh_packetlen) > r) { HWTRACE(DOTRACE_NET, "nic: slot %d: truncated packet", nd->nd_slot); g_stats.s_epkts++; return 0; } if (ntohs(lh->lh_packetlen) < r) { HWTRACE(DOTRACE_NET, "nic: slot %d: garbage on end of packet", nd->nd_slot); g_stats.s_epkts++; return 0; } if (overrun) { HWTRACE(DOTRACE_NET, "nic: slot %d: overrun", nd->nd_slot); g_stats.s_dpkts++; return 0; } g_stats.s_rpkts++; readdone(nd); return 0; }
static void disk_work(struct disk_data *dd) { int cyl, rotoffset; uint32_t rotdelay; int err; if (dd->dd_timedop) { /* * Something's presently happening. Nothing more happens until * it finishes. */ return; } if ((dd->dd_stat & DISKBIT_INPROGRESS)==0) { /* * Nothing to do. */ return; } if (dd->dd_sect >= dd->dd_totsectors) { HWTRACE(DOTRACE_DISK, "disk: slot %d: Invalid sector", dd->dd_slot); INVSECT(dd->dd_stat); dd->dd_worktries = 0; return; } dd->dd_worktries++; if (dd->dd_worktries > MAX_WORKTRIES) { msg("Geometry modeling fault! Please report to maintainer."); HWTRACE(DOTRACE_DISK, "disk: slot %d: Too many loops through timing code!", dd->dd_slot); HWTRACE(DOTRACE_DISK, "disk: current track %d; arrival %u.%09u; iostatus %d", dd->dd_current_track, dd->dd_trackarrival_secs, dd->dd_trackarrival_nsecs, dd->dd_iostatus); dd->dd_current_track = 0; clock_time(&dd->dd_trackarrival_secs, &dd->dd_trackarrival_nsecs); dd->dd_iostatus = -1; dd->dd_timedop = 0; /* skip over all the timing crap */ goto forceio; } locate_sector(dd, dd->dd_sect, &cyl, &rotoffset); if (dd->dd_current_track != cyl) { /* * Need to seek. */ uint32_t nsecs; int distance; distance = cyl - dd->dd_current_track; if (distance<0) { distance = -distance; } nsecs = disk_seektime(dd, distance); HWTRACE(DOTRACE_DISK, "disk: slot %d: seeking to track %d: %u ns", dd->dd_slot, cyl, nsecs); dd->dd_timedop = 1; schedule_event(nsecs, dd, cyl, disk_seekdone, "disk seek"); return; } if (dd->dd_stat & DISKBIT_ISWRITE && dd->dd_iostatus < 1) { //HWTRACE(DOTRACE_DISK, "disk: slot %d: write copy latency", // dd->dd_slot); dd->dd_timedop = 1; schedule_event(CACHE_WRITE_TIME, dd, 1, disk_waitdone, "disk cache write"); return; } if (dd->dd_iostatus < 2) { if (dd->dd_stat & DISKBIT_ISWRITE) { rotdelay = disk_writerotdelay(dd, cyl, rotoffset); } else { rotdelay = disk_readrotdelay(dd, cyl, rotoffset); } if (rotdelay > 0) { HWTRACE(DOTRACE_DISK, "disk: slot %d: rotdelay %u ns", dd->dd_slot, rotdelay); dd->dd_timedop = 1; schedule_event(rotdelay, dd, 2, disk_waitdone, "disk rotation"); return; } else { HWTRACE(DOTRACE_DISK, "disk: slot %d: rotdelay 0 ns", dd->dd_slot); dd->dd_iostatus = 2; } } if ((dd->dd_stat & DISKBIT_ISWRITE)==0 && dd->dd_iostatus < 3) { //HWTRACE(DOTRACE_DISK, "disk: slot %d: read copy latency", // dd->dd_slot); dd->dd_timedop = 1; schedule_event(CACHE_READ_TIME, dd, 3, disk_waitdone, "disk cache read"); return; } forceio: /* * We're here. */ if (dd->dd_stat & DISKBIT_ISWRITE) { HWTRACE(DOTRACE_DISK, "disk: slot %d: write sector %u", dd->dd_slot, dd->dd_sect); err = disk_writesector(dd); } else { HWTRACE(DOTRACE_DISK, "disk: slot %d: read sector %u", dd->dd_slot, dd->dd_sect); err = disk_readsector(dd); } if (err) { HWTRACE(DOTRACE_DISK, "disk: slot %d: media error", dd->dd_slot); MEDIAERR(dd->dd_stat); dd->dd_worktries = 0; } else { COMPLETE(dd->dd_stat); dd->dd_worktries = 0; } }