Running FreeBSD on Firebox III
Sakai, Kazuhiro
kazuhiro at robios.org
Sun Mar 2 16:26:48 UTC 2008
Hi,
Yes, I found it, and I'm sure it will help your problem, too.
I found the difference between the FreeBSD ata driver and the Linux
ata driver. It is called the VLB (Vesa Local Bus, maybe) Sync, and
seems it's been introduced since the Linux 1.2 kernel. The VLB Sync
is a very small routine. Here's the Linux version (2.2.26) (ide.c):
#if SUPPORT_VLB_SYNC
/*
* Some localbus EIDE interfaces require a special access sequence
* when using 32-bit I/O instructions to transfer data. We call this
* the "vlb_sync" sequence, which consists of three successive reads
* of the sector count register location, with interrupts disabled
* to ensure that the reads all happen together.
*/
static inline void do_vlb_sync (ide_ioreg_t port) {
(void) inb (port);
(void) inb (port);
(void) inb (port);
}
#endif /* SUPPORT_VLB_SYNC */
So I ported it to FreeBSD 4.11 for the m0n0wall as:
/sys/dev/ata/ata-disk.c:
* Add ad_vlb_sync
static __inline void
ad_vlb_sync(struct resource *port)
{
(void)ATA_INB(port, ATA_SECTOR);
(void)ATA_INB(port, ATA_SECTOR);
(void)ATA_INB(port, ATA_SECTOR);
}
* Modify ad_transfer and ad_interrupt
int
ad_transfer(struct ad_request *request)
{
...
/* output the data */
if (adp->device->channel->flags & ATA_USE_16BIT)
ATA_OUTSW(adp->device->channel->r_io, ATA_DATA,
(void *)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int16_t));
- else
+ else {
+ disable_intr();
+ ad_vlb_sync(adp->device->channel->r_io);
ATA_OUTSL(adp->device->channel->r_io, ATA_DATA,
(void *)((uintptr_t)request->data + request-
>donecount),
request->currentsize / sizeof(int32_t));
+ enable_intr();
+ }
...
}
int
ad_interrupt(struct ad_request *request)
{
...
/* ready to receive data? */
if ((adp->device->channel->status & (ATA_S_READY|ATA_S_DSC|
ATA_S_DRQ))
!= (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ))
ata_prtdev(adp->device, "read interrupt arrived early");
if (ata_wait(adp->device, (ATA_S_READY | ATA_S_DSC |
ATA_S_DRQ)) != 0) {
ata_prtdev(adp->device, "read error detected (too) late");
request->flags |= ADR_F_ERROR;
}
else {
/* data ready, read in */
if (adp->device->channel->flags & ATA_USE_16BIT)
ATA_INSW(adp->device->channel->r_io, ATA_DATA,
(void*)((uintptr_t)request->data + request-
>donecount),
request->currentsize / sizeof(int16_t));
- else
+ else {
+ disable_intr();
+ ad_vlb_sync(adp->device->channel->r_io);
ATA_INSL(adp->device->channel->r_io, ATA_DATA,
(void*)((uintptr_t)request->data + request-
>donecount),
request->currentsize / sizeof(int32_t));
+ enable_intr();
+ }
}
}
...
}
Next, to get a correct Ether Station Address (MAC Address), make a
following change (just commenting out) in the Tulip driver:
/sys/pci/if_dc.c (/sys/dev/ic/dc.c for OpenBSD):
* Modify dc_attach
/*
* Get station address from the EEPROM.
*/
switch(sc->dc_type) {
case DC_TYPE_98713:
case DC_TYPE_98713A:
- case DC_TYPE_987x5:
+ /*case DC_TYPE_987x5:*/
case DC_TYPE_PNICII:
These should help.
P.S.
I'm wondering why the VLB Sync is not implemented in the BSD family.
I am planning to submit a patch to the m0n0wall community, as well as
the FreeBSD itself maybe.
On 2008/03/01, at 7:47, James Records wrote:
> Hi,
>
> I was just wondering if you ever found a workaround to this, I'm in
> the process of trying to run OpenBSD and running into the exact
> same thing.
>
> If you have any update I would really like to know.
>
> Thanks,
> Jim
Sakai, Kazuhiro
kazuhiro at robios.org
More information about the freebsd-drivers
mailing list