~vdupras/duskbsd

2a8a4911ad7be96e36369f7f2cf5fe6b50f5b023 — Virgil Dupras 11 months ago b4a5569
ata: wd_readsector() was ported!
3 files changed, 4 insertions(+), 79 deletions(-)

M dev/ata/wd.c
M dev/ata/wdvar.h
M kern/kexec.c
M dev/ata/wd.c => dev/ata/wd.c +0 -67
@@ 774,73 774,6 @@ wdstart1(struct wd_softc *wd, struct buf *bp, struct ata_xfer *xfer)
	}
}

// DuskBSD hacking
extern void ata_activate_xfer_locked(struct ata_channel *, struct ata_xfer *);
int (*dusk_wdc_ata_bio_start)(struct ata_channel *chp, struct ata_xfer *xfer) = NULL;
int wd_readsector(device_t dev, unsigned int blkno, void *dst);
int wd_readsector(device_t dev, unsigned int blkno, void *dst) {
	struct wd_softc *wd = device_private(dev);
	struct dk_softc *dksc = &wd->sc_dksc;
	struct disk_geom *geom = &dksc->sc_dkdev.dk_geom;
	struct ata_drive_datas *drvp = wd->drvp;
	struct ata_channel *chp = drvp->chnl_softc;
	struct ata_xfer xfer = {0};
	struct ata_bio *ata_bio = &xfer.c_bio;

	ata_bio->blkno = blkno;
	ata_bio->databuf = dst;
	ata_bio->blkdone = 0;
	ata_bio->bp = NULL;
	ata_bio->flags = ATA_READ;

	/*
	 * request LBA48 transfers when supported by the controller
	 * and needed by transfer offset or size.
	 */
	if (wd->sc_flags & WDF_LBA48 &&
	    (((ata_bio->blkno + ata_bio->bcount / geom->dg_secsize) > wd->sc_capacity28) ||
	    ((ata_bio->bcount / geom->dg_secsize) > 128))) {
		panic("ATA_LBA48 not supported");
		return 1;
	}

	// TODO: what is NCQ? FUA?

	if (wd->sc_flags & WDF_LBA) ata_bio->flags |= ATA_LBA;

	// This is ata_wdc.c:wdc_ata_bio() inlined
	// we force polling mode
	ata_bio->flags |= ATA_POLL;
	xfer.c_flags |= C_POLL;
	xfer.c_drive = drvp->drive;
	xfer.c_databuf = ata_bio->databuf;
	// This is an inline of ata.c:ata_exec_xfer()
	ATADEBUG_PRINT(("ata_exec_xfer %p channel %d drive %d\n", &xfer,
	    chp->ch_channel, xfer.c_drive), DEBUG_XFERS);

	/* complete xfer setup */
	xfer.c_chp = chp;

	ATADEBUG_PRINT(("atastart from ata_exec_xfer, flags 0x%x\n",
	    chp->ch_flags), DEBUG_XFERS);
	// Inlining ata.c:atastart()
	ata_channel_lock(chp);

	ATADEBUG_PRINT(("%s(chp=%p): xfer %p channel %d drive %d\n",
	    __func__, chp, &xfer, chp->ch_channel, xfer.c_drive), DEBUG_XFERS);
	if (drvp->drive_flags & ATA_DRIVE_RESET) {
		drvp->drive_flags &= ~ATA_DRIVE_RESET;
		drvp->state = 0;
	}

	CLR(chp->ch_flags, ATACH_NCQ);

	ata_activate_xfer_locked(chp, &xfer);

	KASSERT(mutex_owned(&chp->ch_lock));
	return dusk_wdc_ata_bio_start(chp, &xfer);
}

static int
wd_diskstart(device_t dev, struct buf *bp)
{

M dev/ata/wdvar.h => dev/ata/wdvar.h +3 -7
@@ 36,14 36,11 @@

struct wd_softc {
	/* General disk infos */
	struct dk_softc sc_dksc;
	kmutex_t sc_lock;
	int sc_quirks;			/* any quirks drive might have */

	/* IDE disk soft states */
	struct ata_drive_datas *drvp; /* Our controller's infos */
	const struct ata_bustype *atabus;
	struct ataparams sc_params;/* drive characteristics found */
	int sc_flags;
/*
 * XXX Nothing resets this yet, but disk change sensing will when ATA-4 is


@@ 59,6 56,8 @@ struct wd_softc {
	uint64_t sc_capacity512; /* ... in DEV_BSIZE blocks */
	uint32_t sc_capacity28; /* capacity accessible with LBA28 commands */
	uint32_t sc_blksize; /* logical block size, in bytes */
	struct dk_softc sc_dksc;
	struct ataparams sc_params;/* drive characteristics found */
	struct disk_sectoralign sc_sectoralign; /* sector alignment */

#ifdef WD_SOFTBADSECT


@@ 84,12 83,9 @@ struct wd_softc {
	bool drv_ncq_prio;
#define WD_USE_NCQ_PRIO(wd) \
	((wd)->drv_ncq_prio && ((wd)->drvp->drive_flags & ATA_DRIVE_NCQ_PRIO))
#ifdef WD_CHAOS_MONKEY
	int drv_chaos_freq;		/* frequency of simulated bio errors */
	int drv_chaos_cnt;		/* count of processed bio read xfers */
#endif
	unsigned inflight;
	char *sc_typename;
	kmutex_t sc_lock;
};

#endif /* _DEV_ATA_WDVAR_H_ */

M kern/kexec.c => kern/kexec.c +1 -5
@@ 13,7 13,6 @@
void kexec(void);
extern struct cfdriver wsdisplay_cd;
extern struct devicelist alldevs; // kern/subr_autoconf.c
extern int wd_readsector(device_t dev, unsigned int blkno, void *dst);

/* DuskBSD's FSID are the vnodes themselves
 * Because NetBSD ensures that a there's ever only one vnode to a file, we can


@@ 297,9 296,7 @@ static unsigned int _gettick(void) {
// to worry about destroying PS-top. Just keep the callbacks PS-neutral.
// Also, avoid making callbacks "call back" into the kernel. It might lead to
// nasty stuff. Therefore, no emit.
extern void *dusk_wdc_ata_bio_start;
static void _setcallbacks(void **callbacks) {
    dusk_wdc_ata_bio_start = callbacks[0];
}
struct KexecAPI {
	void (*reboot)(void);


@@ 326,7 323,6 @@ struct KexecAPI {
	struct vnode *rootvnode;	// vnode corresponding to mounted FS
	struct vnode *kexecvnode;	// vnode of /kexec, for self-hosting purposes
	device_t wsdisplaydev;
	int (*wd_readsector)(device_t, unsigned int, void*);
	void (*setcallbacks)(void**);
} __packed;
static struct KexecAPI kexecapi = {


@@ 335,7 331,7 @@ static struct KexecAPI kexecapi = {
	_vnresize, _vnflush, _vnnewfile, _vnnewdir, _vnodeinfo, _vnodeiter,
	_gettick,
	0, NULL, NULL, NULL, NULL, NULL,
	wd_readsector, _setcallbacks};
	_setcallbacks};

/* DuskBSD fixed addressing