Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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");
}
Ejemplo n.º 3
0
void
lower_irq(int slot)
{
	bus_raised_interrupts &= ~((uint32_t)1 << slot);
	irqupdate();
	HWTRACE(DOTRACE_IRQ, "Slot %2d: irq OFF", (slot));
}
Ejemplo n.º 4
0
void
raise_irq(int slot)
{
	bus_raised_interrupts |= ((uint32_t)1 << slot);
	irqupdate();
	HWTRACE(DOTRACE_IRQ, "Slot %2d: irq ON", (slot));
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
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;
    }

}