at_wini: PCI-only now; one controller per instance

- remove non-PCI support, since all supported platforms with at_wini
  devices also have PCI support by now;
- correspondingly, stop using information from the BIOS altogether;
- limit each driver instance to one controller, to be in line with
  the general MINIX3 one-instance-per-controller driver model; this
  limits the number of disks per at_wini instance to four;
- go through the controllers by the order of their occurrence in the
  PCI table, thus removing the exception for compatibility devices;
- let the second at_wini instance shut down silently if there is only
  one IDE controller;
- clean up some extra code we don't need anymore, and resolve some
  WARNS=5 level warnings.

Overall, these changes should simplify automatic loading of the right
disk drivers at boot time in the future.

Change-Id: Ia64d08cfbeb9916abd68c9c2941baeb87d02a806
This commit is contained in:
David van Moolenbroek 2013-10-02 19:37:00 +02:00 committed by Lionel Sambuc
parent 89332ecdf1
commit 6d466f941b
5 changed files with 251 additions and 516 deletions

View File

@ -1,11 +1,8 @@
/* This file contains the device dependent part of a driver for the IBM-AT /* This file contains the device dependent part of a driver for the IBM-AT
* winchester controller. Written by Adri Koppes. * winchester controller. Written by Adri Koppes.
* *
* The file contains one entry point:
*
* at_winchester_task: main entry when system is brought up
*
* Changes: * Changes:
* Oct 2, 2013 drop non-PCI support; one controller per instance (David)
* Aug 19, 2005 ATA PCI support, supports SATA (Ben Gras) * Aug 19, 2005 ATA PCI support, supports SATA (Ben Gras)
* Nov 18, 2004 moved AT disk driver to user-space (Jorrit N. Herder) * Nov 18, 2004 moved AT disk driver to user-space (Jorrit N. Herder)
* Aug 20, 2004 watchdogs replaced by sync alarms (Jorrit N. Herder) * Aug 20, 2004 watchdogs replaced by sync alarms (Jorrit N. Herder)
@ -58,34 +55,24 @@ static long w_atapi_dma;
static int w_testing = 0; static int w_testing = 0;
static int w_silent = 0; static int w_silent = 0;
static int w_next_drive = 0;
static u32_t system_hz; static u32_t system_hz;
/* The struct wini is indexed by controller first, then drive (0-3). /* The struct wini is indexed by drive (0-3). */
* Controller 0 is always the 'compatability' ide controller, at
* the fixed locations, whether present or not.
*/
static struct wini { /* main drive struct, one entry per drive */ static struct wini { /* main drive struct, one entry per drive */
unsigned state; /* drive state: deaf, initialized, dead */ unsigned state; /* drive state: deaf, initialized, dead */
unsigned short w_status; /* device status register */ unsigned short w_status; /* device status register */
unsigned base_cmd; /* command base register */ unsigned base_cmd; /* command base register */
unsigned base_ctl; /* control base register */ unsigned base_ctl; /* control base register */
unsigned base_dma; /* dma base register */ unsigned base_dma; /* dma base register */
int dma_intseen; unsigned char native; /* if set, drive is native (not compat.) */
unsigned irq; /* interrupt request line */ unsigned char lba48; /* if set, drive supports lba48 */
unsigned irq_need_ack; /* irq needs to be acknowledged */ unsigned char dma; /* if set, drive supports dma */
unsigned char dma_intseen; /* if set, drive has seen an interrupt */
int irq_hook_id; /* id of irq hook at the kernel */ int irq_hook_id; /* id of irq hook at the kernel */
int lba48; /* supports lba48 */ unsigned cylinders; /* physical number of cylinders */
int dma; /* supports dma */ unsigned heads; /* physical number of heads */
unsigned lcylinders; /* logical number of cylinders (BIOS) */ unsigned sectors; /* physical number of sectors per track */
unsigned lheads; /* logical number of heads */
unsigned lsectors; /* logical number of sectors per track */
unsigned pcylinders; /* physical number of cylinders (translated) */
unsigned pheads; /* physical number of heads */
unsigned psectors; /* physical number of sectors per track */
unsigned ldhpref; /* top four bytes of the LDH (head) register */ unsigned ldhpref; /* top four bytes of the LDH (head) register */
unsigned precomp; /* write precompensation cylinder / 4 */
unsigned max_count; /* max request for this drive */ unsigned max_count; /* max request for this drive */
unsigned open_ct; /* in-use count */ unsigned open_ct; /* in-use count */
struct device part[DEV_PER_DRIVE]; /* disks and partitions */ struct device part[DEV_PER_DRIVE]; /* disks and partitions */
@ -122,24 +109,9 @@ static phys_bytes prdt_phys;
#define PRDTE_FL_EOT 0x80 /* End of table */ #define PRDTE_FL_EOT 0x80 /* End of table */
/* IDE devices we trust are IDE devices. */ static int w_probe(int skip, u16_t *vidp, u16_t *didp);
static struct quirk static void w_init(int devind, u16_t vid, u16_t did);
{ static int init_params(void);
int pci_class, pci_subclass, pci_interface;
u16_t vendor;
u16_t device;
} quirk_table[]=
{
{ 0x01, 0x04, 0x00, 0x1106, 0x3149 }, /* VIA VT6420 */
{ 0x01, 0x04, 0x00, 0x1095, 0x3512 },
{ 0x01, 0x80, -1, 0x1095, 0x3114 }, /* Silicon Image SATA */
{ 0, 0, 0, 0, 0 } /* end of list */
};
static void init_params(void);
static void init_drive(struct wini *w, int base_cmd, int base_ctl, int
base_dma, int irq, int ack, int hook, int drive);
static void init_params_pci(int);
static int w_do_open(devminor_t minor, int access); static int w_do_open(devminor_t minor, int access);
static struct device *w_prepare(devminor_t dev); static struct device *w_prepare(devminor_t dev);
static struct device *w_part(devminor_t minor); static struct device *w_part(devminor_t minor);
@ -154,7 +126,6 @@ static int com_out_ext(struct command *cmd);
static int setup_dma(unsigned *sizep, endpoint_t proc_nr, iovec_t *iov, static int setup_dma(unsigned *sizep, endpoint_t proc_nr, iovec_t *iov,
size_t addr_offset, int do_write); size_t addr_offset, int do_write);
static void w_need_reset(void); static void w_need_reset(void);
static void ack_irqs(unsigned int);
static int w_do_close(devminor_t minor); static int w_do_close(devminor_t minor);
static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
cp_grant_id_t grant, endpoint_t user_endpt); cp_grant_id_t grant, endpoint_t user_endpt);
@ -165,34 +136,14 @@ static int w_reset(void);
static void w_intr_wait(void); static void w_intr_wait(void);
static int at_intr_wait(void); static int at_intr_wait(void);
static int w_waitfor(int mask, int value); static int w_waitfor(int mask, int value);
static int w_waitfor_dma(int mask, int value); static int w_waitfor_dma(unsigned int mask, unsigned int value);
static void w_geometry(devminor_t minor, struct part_geom *entry); static void w_geometry(devminor_t minor, struct part_geom *entry);
#if ENABLE_ATAPI
static int atapi_sendpacket(u8_t *packet, unsigned cnt, int do_dma); static int atapi_sendpacket(u8_t *packet, unsigned cnt, int do_dma);
static int atapi_intr_wait(int dma, size_t max); static int atapi_intr_wait(int dma, size_t max);
static int atapi_open(void); static int atapi_open(void);
static void atapi_close(void); static void atapi_close(void);
static int atapi_transfer(int do_write, u64_t position, endpoint_t static int atapi_transfer(int do_write, u64_t position, endpoint_t
endpt, iovec_t *iov, unsigned int nr_req); endpt, iovec_t *iov, unsigned int nr_req);
#endif
#define sys_voutb(out, n) at_voutb((out), (n))
static int at_voutb(pvb_pair_t *, int n);
#define sys_vinb(in, n) at_vinb((in), (n))
static int at_vinb(pvb_pair_t *, int n);
#undef sys_outb
#undef sys_inb
#undef sys_outl
static int at_out(int line, u32_t port, u32_t value, char *typename,
int type);
static int at_in(int line, u32_t port, u32_t *value, char *typename,
int type);
#define sys_outb(p, v) at_out(__LINE__, (p), (v), "outb", _DIO_BYTE)
#define sys_inb(p, v) at_in(__LINE__, (p), (v), "inb", _DIO_BYTE)
#define sys_outl(p, v) at_out(__LINE__, (p), (v), "outl", _DIO_LONG)
/* Entry points to this driver. */ /* Entry points to this driver. */
static struct blockdriver w_dtab = { static struct blockdriver w_dtab = {
@ -209,9 +160,6 @@ static struct blockdriver w_dtab = {
/* SEF functions and variables. */ /* SEF functions and variables. */
static void sef_local_startup(void); static void sef_local_startup(void);
static int sef_cb_init_fresh(int type, sef_init_info_t *info); static int sef_cb_init_fresh(int type, sef_init_info_t *info);
EXTERN int sef_cb_lu_prepare(int state);
EXTERN int sef_cb_lu_state_isvalid(int state);
EXTERN void sef_cb_lu_state_dump(int state);
/*===========================================================================* /*===========================================================================*
* at_winchester_task * * at_winchester_task *
@ -252,6 +200,9 @@ static void sef_local_startup(void)
static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
{ {
/* Initialize the at_wini driver. */ /* Initialize the at_wini driver. */
int skip, devind;
u16_t vid, did;
system_hz = sys_hz(); system_hz = sys_hz();
if (!(tmp_buf = alloc_contig(2*DMA_BUF_SIZE, AC_ALIGN4K, NULL))) if (!(tmp_buf = alloc_contig(2*DMA_BUF_SIZE, AC_ALIGN4K, NULL)))
@ -261,7 +212,23 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
wakeup_ticks = WAKEUP_TICKS; wakeup_ticks = WAKEUP_TICKS;
/* Set special disk parameters. */ /* Set special disk parameters. */
init_params(); skip = init_params();
/* Find the PCI device to use. If none found, terminate immediately. */
devind = w_probe(skip, &vid, &did);
if (devind < 0) {
/* For now, complain only if even the first at_wini instance cannot
* find a device. There may be only one IDE controller after all,
* but if there are none, the system should probably be booted with
* another driver, and that's something the user might want to know.
*/
if (w_instance == 0)
panic("no matching device found");
return ENODEV; /* the actual error code doesn't matter */
}
/* Initialize the device. */
w_init(devind, vid, did);
/* Announce we are up! */ /* Announce we are up! */
blockdriver_announce(type); blockdriver_announce(type);
@ -272,16 +239,10 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
/*===========================================================================* /*===========================================================================*
* init_params * * init_params *
*===========================================================================*/ *===========================================================================*/
static void init_params(void) static int init_params(void)
{ {
/* This routine is called at startup to initialize the drive parameters. */ /* This routine is called at startup to initialize the drive parameters. */
int drive;
u16_t parv[2];
unsigned int vector, size;
int drive, nr_drives;
struct wini *wn;
u8_t params[16];
int s;
long wakeup_secs = WAKEUP_SECS; long wakeup_secs = WAKEUP_SECS;
/* Boot variables. */ /* Boot variables. */
@ -316,75 +277,32 @@ static void init_params(void)
} }
} }
if (w_instance == 0) { for (drive = 0; drive < MAX_DRIVES; drive++)
/* Get the number of drives from the BIOS data area */ wini[drive].state = IGNORING;
s=sys_readbios(NR_HD_DRIVES_ADDR, params, NR_HD_DRIVES_SIZE);
if (s != OK)
panic("Couldn't read BIOS: %d", s);
if ((nr_drives = params[0]) > 2) nr_drives = 2;
for (drive = 0, wn = wini; drive < COMPAT_DRIVES; drive++, wn++) { return (int) w_instance;
if (drive < nr_drives) {
/* Copy the BIOS parameter vector */
vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR :
BIOS_HD1_PARAMS_ADDR;
size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE :
BIOS_HD1_PARAMS_SIZE;
s=sys_readbios(vector, parv, size);
if (s != OK)
panic("Couldn't read BIOS: %d", s);
/* Calculate the address of the parameters and copy them */
s=sys_readbios(hclick_to_physb(parv[1]) + parv[0],
params, 16L);
if (s != OK)
panic("Couldn't copy parameters: %d", s);
/* Copy the parameters to the structures of the drive */
wn->lcylinders = bp_cylinders(params);
wn->lheads = bp_heads(params);
wn->lsectors = bp_sectors(params);
wn->precomp = bp_precomp(params) >> 2;
} }
/* Fill in non-BIOS parameters. */
init_drive(wn,
drive < 2 ? REG_CMD_BASE0 : REG_CMD_BASE1,
drive < 2 ? REG_CTL_BASE0 : REG_CTL_BASE1,
0 /* no DMA */, NO_IRQ, 0, 0, drive);
w_next_drive++;
}
}
/* Look for controllers on the pci bus. Skip none the first instance,
* skip one and then 2 for every instance, for every next instance.
*/
if (w_instance == 0)
init_params_pci(0);
else
init_params_pci(w_instance*2-1);
}
#define ATA_IF_NOTCOMPAT1 (1L << 0)
#define ATA_IF_NOTCOMPAT2 (1L << 2)
/*===========================================================================* /*===========================================================================*
* init_drive * * init_drive *
*===========================================================================*/ *===========================================================================*/
static void init_drive(struct wini *w, int base_cmd, int base_ctl, static void init_drive(int drive, int base_cmd, int base_ctl, int base_dma,
int base_dma, int irq, int ack, int hook, int drive) int native, int hook)
{ {
struct wini *w;
w = &wini[drive];
w->state = 0; w->state = 0;
w->w_status = 0; w->w_status = 0;
w->base_cmd = base_cmd; w->base_cmd = base_cmd;
w->base_ctl = base_ctl; w->base_ctl = base_ctl;
w->base_dma = base_dma; w->base_dma = base_dma;
if (w_pci_debug) if (w_pci_debug)
printf("at_wini%ld: drive %d: base_cmd 0x%x, base_ctl 0x%x, base_dma 0x%x\n", printf("at_wini%ld: drive %d: base_cmd 0x%x, base_ctl 0x%x, "
w_instance, w-wini, w->base_cmd, w->base_ctl, w->base_dma); "base_dma 0x%x\n", w_instance, drive, w->base_cmd, w->base_ctl,
w->irq = irq; w->base_dma);
w->irq_need_ack = ack; w->native = native;
w->irq_hook_id = hook; w->irq_hook_id = hook;
w->ldhpref = ldh_init(drive); w->ldhpref = ldh_init(drive);
w->max_count = MAX_SECS << SECTOR_SHIFT; w->max_count = MAX_SECS << SECTOR_SHIFT;
@ -392,188 +310,144 @@ static void init_drive(struct wini *w, int base_cmd, int base_ctl,
w->dma = 0; w->dma = 0;
} }
static int quirkmatch(struct quirk *table, u8_t bcr, u8_t scr, u8_t interface, u16_t vid, u16_t did) { /*===========================================================================*
while(table->vendor) { * w_probe *
if(table->vendor == vid && table->device == did && *===========================================================================*/
table->pci_class == bcr && static int w_probe(int skip, u16_t *vidp, u16_t *didp)
table->pci_subclass == scr &&
(table->pci_interface == -1 ||
table->pci_interface == interface)) {
return 1;
}
table++;
}
return 0;
}
static void
pci_busmaster(int devind)
{ {
u16_t cr; /* Go through the PCI devices that have been made visible to us, skipping as
* many as requested and then reserving the first one after that. We assume
* that all visible devices are in fact devices we can handle.
*/
int r, devind;
/* Enable busmastering if necessary. */ pci_init();
cr = pci_attr_r16(devind, PCI_CR);
if (!(cr & PCI_CR_MAST_EN)) { r = pci_first_dev(&devind, vidp, didp);
pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN); if (r <= 0)
return -1;
while (skip--) {
r = pci_next_dev(&devind, vidp, didp);
if (r <= 0)
return -1;
} }
pci_reserve(devind);
return devind;
} }
/*===========================================================================* /*===========================================================================*
* init_params_pci * * w_init *
*===========================================================================*/ *===========================================================================*/
static void init_params_pci(int skip) static void w_init(int devind, u16_t vid, u16_t did)
{ {
int i, r, devind, drive, pci_compat = 0; /* Initialize drives on the controller that we found and reserved. Each
int irq, irq_hook; * controller has two channels, each of which may have up to two disks
u8_t bcr, scr, interface; * attached, so the maximum number of disks per controller is always four.
u16_t vid, did; * In this function, we always initialize the slots for all four disks; later,
u32_t base_dma, t3; * during normal operation, we determine whether the disks are actually there.
* For pure IDE devices (as opposed to e.g. RAID devices), each of the two
pci_init(); * channels on the controller may be in native or compatibility mode. The PCI
for(drive = w_next_drive; drive < MAX_DRIVES; drive++) * interface field tells us which channel is in which mode. For native
wini[drive].state = IGNORING; * channels, we get the IRQ and the channel's base control and command
for(r = pci_first_dev(&devind, &vid, &did); r != 0; * addresses from the PCI slot, and we manually acknowledge interrupts. For
r = pci_next_dev(&devind, &vid, &did)) { * compatibility channels, we use the hardcoded legacy IRQs and addresses, and
int quirk = 0; * enable automatic IRQ reenabling. In both cases, we get the base DMA address
* from the PCI slot if it is there.
/* Except class 01h (mass storage), subclass be 01h (ATA).
* Also check listed RAID controllers.
*/ */
int r, irq, native_hook, compat_hook, is_ide, nhooks;
u8_t bcr, scr, interface;
u16_t cr;
u32_t base_cmd, base_ctl, base_dma;
bcr= pci_attr_r8(devind, PCI_BCR); bcr= pci_attr_r8(devind, PCI_BCR);
scr= pci_attr_r8(devind, PCI_SCR); scr= pci_attr_r8(devind, PCI_SCR);
interface= pci_attr_r8(devind, PCI_PIFR); interface= pci_attr_r8(devind, PCI_PIFR);
t3= ((bcr << 16) | (scr << 8) | interface);
if (bcr == PCI_BCR_MASS_STORAGE && scr == PCI_MS_IDE)
; /* Okay */
else if(quirkmatch(quirk_table, bcr, scr, interface, vid, did)) {
quirk = 1;
} else
continue; /* Unsupported device class */
/* Found a controller. is_ide = (bcr == PCI_BCR_MASS_STORAGE && scr == PCI_MS_IDE);
* Programming interface register tells us more.
*/
irq = pci_attr_r8(devind, PCI_ILR); irq = pci_attr_r8(devind, PCI_ILR);
/* Any non-compat drives? */
if (quirk || (interface & (ATA_IF_NOTCOMPAT1 | ATA_IF_NOTCOMPAT2))) {
if (w_next_drive >= MAX_DRIVES)
{
/* We can't accept more drives, but have to search for
* controllers operating in compatibility mode.
*/
continue;
}
irq_hook = irq;
if (skip > 0) {
if (w_pci_debug)
{
printf(
"atapci skipping controller (remain %d)\n",
skip);
}
skip--;
continue;
}
if(pci_reserve_ok(devind) != OK) {
printf("at_wini%ld: pci_reserve %d failed - "
"ignoring controller!\n",
w_instance, devind);
continue;
}
pci_busmaster(devind);
if (sys_irqsetpolicy(irq, 0, &irq_hook) != OK) {
printf("atapci: couldn't set IRQ policy %d\n", irq);
continue;
}
if (sys_irqenable(&irq_hook) != OK) {
printf("atapci: couldn't enable IRQ line %d\n", irq);
continue;
}
}
base_dma = pci_attr_r32(devind, PCI_BAR_5) & PCI_BAR_IO_MASK; base_dma = pci_attr_r32(devind, PCI_BAR_5) & PCI_BAR_IO_MASK;
/* Primary channel not in compatability mode? */ nhooks = 0; /* we don't care about notify IDs, but they must be unique */
if (quirk || (interface & ATA_IF_NOTCOMPAT1)) {
u32_t base_cmd, base_ctl;
/* Any native drives? Then register their native IRQ first. */
if (!is_ide || (interface & (ATA_IF_NATIVE0 | ATA_IF_NATIVE1))) {
native_hook = nhooks++;
if ((r = sys_irqsetpolicy(irq, 0, &native_hook)) != OK)
panic("couldn't set native IRQ policy %d: %d", irq, r);
if ((r = sys_irqenable(&native_hook)) != OK)
panic("couldn't enable native IRQ line %d: %d", irq, r);
}
/* Add drives on the primary channel. */
if (!is_ide || (interface & ATA_IF_NATIVE0)) {
base_cmd = pci_attr_r32(devind, PCI_BAR) & PCI_BAR_IO_MASK; base_cmd = pci_attr_r32(devind, PCI_BAR) & PCI_BAR_IO_MASK;
base_ctl = pci_attr_r32(devind, PCI_BAR_2) & PCI_BAR_IO_MASK; base_ctl = pci_attr_r32(devind, PCI_BAR_2) & PCI_BAR_IO_MASK;
if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) {
init_drive(&wini[w_next_drive], init_drive(0, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
base_cmd, base_ctl+PCI_CTL_OFF, native_hook);
base_dma, irq, 1, irq_hook, 0); init_drive(1, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
init_drive(&wini[w_next_drive+1], native_hook);
base_cmd, base_ctl+PCI_CTL_OFF,
base_dma, irq, 1, irq_hook, 1);
if (w_pci_debug) if (w_pci_debug)
printf("at_wini%ld: atapci %d: 0x%x 0x%x irq %d\n", printf("at_wini%ld: native 0 on %d: 0x%x 0x%x irq %d\n",
w_instance, devind, base_cmd, base_ctl, irq); w_instance, devind, base_cmd, base_ctl, irq);
w_next_drive += 2; } else {
} else printf("at_wini%ld: atapci: ignored drives on primary channel, base %x\n", w_instance, base_cmd); /* Register first compatibility IRQ. */
} compat_hook = nhooks++;
else if ((r = sys_irqsetpolicy(AT_WINI_0_IRQ, IRQ_REENABLE,
{ &compat_hook)) != OK)
/* Update base_dma for compatibility device */ panic("couldn't set compat(0) IRQ policy: %d", r);
for (i= 0; i<MAX_DRIVES; i++) if ((r = sys_irqenable(&compat_hook)) != OK)
{ panic("couldn't enable compat(0) IRQ line: %d", r);
if (wini[i].base_cmd == REG_CMD_BASE0) {
wini[i].base_dma= base_dma; init_drive(0, REG_CMD_BASE0, REG_CTL_BASE0, base_dma, FALSE,
compat_hook);
init_drive(1, REG_CMD_BASE0, REG_CTL_BASE0, base_dma, FALSE,
compat_hook);
if (w_pci_debug) if (w_pci_debug)
printf("at_wini%ld: drive %d: base_dma 0x%x\n", printf("at_wini%ld: compat 0 on %d\n", w_instance, devind);
w_instance, i, wini[i].base_dma);
pci_compat = 1;
}
}
} }
/* Secondary channel not in compatability mode? */ /* Add drives on the secondary channel. */
if (quirk || (interface & ATA_IF_NOTCOMPAT2)) {
u32_t base_cmd, base_ctl;
base_cmd = pci_attr_r32(devind, PCI_BAR_3) & PCI_BAR_IO_MASK;
base_ctl = pci_attr_r32(devind, PCI_BAR_4) & PCI_BAR_IO_MASK;
if (base_dma != 0) if (base_dma != 0)
base_dma += PCI_DMA_2ND_OFF; base_dma += PCI_DMA_2ND_OFF;
if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) { if (!is_ide || (interface & ATA_IF_NATIVE1)) {
init_drive(&wini[w_next_drive], base_cmd = pci_attr_r32(devind, PCI_BAR_3) & PCI_BAR_IO_MASK;
base_cmd, base_ctl+PCI_CTL_OFF, base_dma, base_ctl = pci_attr_r32(devind, PCI_BAR_4) & PCI_BAR_IO_MASK;
irq, 1, irq_hook, 2); init_drive(2, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
init_drive(&wini[w_next_drive+1], native_hook);
base_cmd, base_ctl+PCI_CTL_OFF, base_dma, init_drive(3, base_cmd, base_ctl+PCI_CTL_OFF, base_dma, TRUE,
irq, 1, irq_hook, 3); native_hook);
if (w_pci_debug) if (w_pci_debug)
printf("at_wini%ld: atapci %d: 0x%x 0x%x irq %d\n", printf("at_wini%ld: native 1 on %d: 0x%x 0x%x irq %d\n",
w_instance, devind, base_cmd, base_ctl, irq); w_instance, devind, base_cmd, base_ctl, irq);
w_next_drive += 2; } else {
} else printf("at_wini%ld: atapci: ignored drives on " /* Register secondary compatibility IRQ. */
"secondary channel, base %x\n", w_instance, base_cmd); compat_hook = nhooks++;
} if ((r = sys_irqsetpolicy(AT_WINI_1_IRQ, IRQ_REENABLE,
else &compat_hook)) != OK)
{ panic("couldn't set compat(1) IRQ policy: %d", r);
/* Update base_dma for compatibility device */ if ((r = sys_irqenable(&compat_hook)) != OK)
for (i= 0; i<MAX_DRIVES; i++) panic("couldn't enable compat(1) IRQ line: %d", r);
{
if (wini[i].base_cmd == REG_CMD_BASE1 && base_dma != 0) { init_drive(2, REG_CMD_BASE1, REG_CTL_BASE1, base_dma, FALSE,
wini[i].base_dma= base_dma+PCI_DMA_2ND_OFF; compat_hook);
init_drive(3, REG_CMD_BASE1, REG_CTL_BASE1, base_dma, FALSE,
compat_hook);
if (w_pci_debug) if (w_pci_debug)
printf("at_wini%ld: drive %d: base_dma 0x%x\n", printf("at_wini%ld: compat 1 on %d\n", w_instance, devind);
w_instance, i, wini[i].base_dma);
pci_compat = 1;
}
}
} }
if(pci_compat) { /* Enable busmastering if necessary. */
if(pci_reserve_ok(devind) != OK) { cr = pci_attr_r16(devind, PCI_CR);
printf("at_wini%ld (compat): pci_reserve %d failed!\n", if (!(cr & PCI_CR_MAST_EN))
w_instance, devind); pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN);
} else pci_busmaster(devind);
}
}
} }
/*===========================================================================* /*===========================================================================*
@ -599,7 +473,7 @@ static int w_do_open(devminor_t minor, int access)
/* Try to identify the device. */ /* Try to identify the device. */
if (w_identify() != OK) { if (w_identify() != OK) {
#if VERBOSE #if VERBOSE
printf("%s: probe failed\n", w_name()); printf("%s: identification failed\n", w_name());
#endif #endif
if (wn->state & DEAF){ if (wn->state & DEAF){
int err = w_reset(); int err = w_reset();
@ -621,21 +495,17 @@ static int w_do_open(devminor_t minor, int access)
} }
} }
#if ENABLE_ATAPI
if ((wn->state & ATAPI) && (access & BDEV_W_BIT)) if ((wn->state & ATAPI) && (access & BDEV_W_BIT))
return(EACCES); return(EACCES);
#endif
/* Partition the drive if it's being opened for the first time, /* Partition the drive if it's being opened for the first time,
* or being opened after being closed. * or being opened after being closed.
*/ */
if (wn->open_ct == 0) { if (wn->open_ct == 0) {
#if ENABLE_ATAPI
if (wn->state & ATAPI) { if (wn->state & ATAPI) {
int r; int r;
if ((r = atapi_open()) != OK) return(r); if ((r = atapi_open()) != OK) return(r);
} }
#endif
/* Partition the disk. */ /* Partition the disk. */
partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY,
@ -655,11 +525,13 @@ static struct device *w_prepare(devminor_t device)
if (device >= 0 && device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */ if (device >= 0 && device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
w_drive = device / DEV_PER_DRIVE; /* save drive number */ w_drive = device / DEV_PER_DRIVE; /* save drive number */
if (w_drive >= MAX_DRIVES) return(NULL);
w_wn = &wini[w_drive]; w_wn = &wini[w_drive];
w_dv = &w_wn->part[device % DEV_PER_DRIVE]; w_dv = &w_wn->part[device % DEV_PER_DRIVE];
} else } else
if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/ if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
w_drive = device / SUB_PER_DRIVE; w_drive = device / SUB_PER_DRIVE;
if (w_drive >= MAX_DRIVES) return(NULL);
w_wn = &wini[w_drive]; w_wn = &wini[w_drive];
w_dv = &w_wn->subpart[device % SUB_PER_DRIVE]; w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
} else { } else {
@ -806,24 +678,14 @@ static int w_identify(void)
if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK) if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)
panic("Call to sys_insw() failed: %d", s); panic("Call to sys_insw() failed: %d", s);
#if 0
if (id_word(0) & ID_GEN_NOT_ATA)
{
printf("%s: not an ATA device?\n", w_name());
wakeup_ticks = prev_wakeup;
w_testing = 0;
return ERR;
}
#endif
/* This is an ATA device. */ /* This is an ATA device. */
wn->state |= SMART; wn->state |= SMART;
/* Preferred CHS translation mode. */ /* Preferred CHS translation mode. */
wn->pcylinders = id_word(1); wn->cylinders = id_word(1);
wn->pheads = id_word(3); wn->heads = id_word(3);
wn->psectors = id_word(6); wn->sectors = id_word(6);
size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors; size = (u32_t) wn->cylinders * wn->heads * wn->sectors;
w= id_word(ID_CAPABILITIES); w= id_word(ID_CAPABILITIES);
if ((w & ID_CAP_LBA) && size > 512L*1024*2) { if ((w & ID_CAP_LBA) && size > 512L*1024*2) {
@ -856,20 +718,7 @@ static int w_identify(void)
check_dma(wn); check_dma(wn);
} }
} else if (cmd.command = ATAPI_IDENTIFY,
if (wn->lcylinders == 0 || wn->lheads == 0 || wn->lsectors == 0) {
/* No BIOS parameters? Then make some up. */
wn->lcylinders = wn->pcylinders;
wn->lheads = wn->pheads;
wn->lsectors = wn->psectors;
while (wn->lcylinders > 1024) {
wn->lheads *= 2;
wn->lcylinders /= 2;
}
}
#if ENABLE_ATAPI
} else
if (cmd.command = ATAPI_IDENTIFY,
com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) && com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) &&
!(wn->w_status & (STATUS_ERR|STATUS_WF))) { !(wn->w_status & (STATUS_ERR|STATUS_WF))) {
/* An ATAPI device. */ /* An ATAPI device. */
@ -881,20 +730,13 @@ static int w_identify(void)
size = 0; /* Size set later. */ size = 0; /* Size set later. */
check_dma(wn); check_dma(wn);
#endif
} else { } else {
/* Not an ATA device; no translations, no special features. Don't /* Not an ATA device; no translations, no special features. Don't
* touch it unless the BIOS knows about it. * touch it.
*/ */
if (wn->lcylinders == 0) {
wakeup_ticks = prev_wakeup; wakeup_ticks = prev_wakeup;
w_testing = 0; w_testing = 0;
return(ERR); return(ERR);
} /* no BIOS parameters */
wn->pcylinders = wn->lcylinders;
wn->pheads = wn->lheads;
wn->psectors = wn->lsectors;
size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
} }
/* Restore wakeup_ticks and unset testing mode. */ /* Restore wakeup_ticks and unset testing mode. */
@ -909,15 +751,6 @@ static int w_identify(void)
return(ERR); return(ERR);
} }
if (wn->irq == NO_IRQ) {
/* Everything looks OK; register IRQ so we can stop polling. */
wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
wn->irq_hook_id = wn->irq; /* id to be returned if interrupt occurs */
if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK)
panic("couldn't set IRQ policy: %d", s);
if ((s=sys_irqenable(&wn->irq_hook_id)) != OK)
panic("couldn't enable IRQ line: %d", s);
}
wn->state |= IDENTIFIED; wn->state |= IDENTIFIED;
return(OK); return(OK);
} }
@ -946,11 +779,7 @@ static int w_io_test(void)
static char *buf; static char *buf;
ssize_t r; ssize_t r;
#ifdef CD_SECTOR_SIZE
#define BUFSIZE CD_SECTOR_SIZE #define BUFSIZE CD_SECTOR_SIZE
#else
#define BUFSIZE SECTOR_SIZE
#endif
STATICINIT(buf, BUFSIZE); STATICINIT(buf, BUFSIZE);
iov.iov_addr = (vir_bytes) buf; iov.iov_addr = (vir_bytes) buf;
@ -971,7 +800,7 @@ static int w_io_test(void)
w_testing = 1; w_testing = 1;
/* Try I/O on the actual drive (not any (sub)partition). */ /* Try I/O on the actual drive (not any (sub)partition). */
r = w_transfer(w_drive * DEV_PER_DRIVE, FALSE /*do_write*/, ((u64_t)(0)), r = w_transfer(w_drive * DEV_PER_DRIVE, FALSE /*do_write*/, 0,
SELF, &iov, 1, BDEV_NOFLAGS); SELF, &iov, 1, BDEV_NOFLAGS);
/* Switch back. */ /* Switch back. */
@ -1009,9 +838,9 @@ static int w_specify(void)
if (!(wn->state & ATAPI)) { if (!(wn->state & ATAPI)) {
/* Specify parameters: precompensation, number of heads and sectors. */ /* Specify parameters: precompensation, number of heads and sectors. */
cmd.precomp = wn->precomp; cmd.precomp = 0;
cmd.count = wn->psectors; cmd.count = wn->sectors;
cmd.ldh = w_wn->ldhpref | (wn->pheads - 1); cmd.ldh = w_wn->ldhpref | (wn->heads - 1);
cmd.command = CMD_SPECIFY; /* Specify some parameters */ cmd.command = CMD_SPECIFY; /* Specify some parameters */
/* Output command block and see if controller accepts the parameters. */ /* Output command block and see if controller accepts the parameters. */
@ -1035,13 +864,12 @@ static int w_specify(void)
/*===========================================================================* /*===========================================================================*
* do_transfer * * do_transfer *
*===========================================================================*/ *===========================================================================*/
static int do_transfer(const struct wini *wn, unsigned int precomp, static int do_transfer(const struct wini *wn, unsigned int count,
unsigned int count, unsigned int sector, unsigned int sector, unsigned int do_write, int do_dma)
unsigned int do_write, int do_dma)
{ {
struct command cmd; struct command cmd;
unsigned int sector_high; unsigned int sector_high;
unsigned secspcyl = wn->pheads * wn->psectors; unsigned secspcyl = wn->heads * wn->sectors;
int do_lba48; int do_lba48;
sector_high= 0; /* For future extensions */ sector_high= 0; /* For future extensions */
@ -1058,7 +886,7 @@ static int do_transfer(const struct wini *wn, unsigned int precomp,
} }
} }
cmd.precomp = precomp; cmd.precomp = 0;
cmd.count = count; cmd.count = count;
if (do_dma) if (do_dma)
{ {
@ -1096,8 +924,8 @@ static int do_transfer(const struct wini *wn, unsigned int precomp,
} else { } else {
int cylinder, head, sec; int cylinder, head, sec;
cylinder = sector / secspcyl; cylinder = sector / secspcyl;
head = (sector % secspcyl) / wn->psectors; head = (sector % secspcyl) / wn->sectors;
sec = sector % wn->psectors; sec = sector % wn->sectors;
cmd.sector = sec + 1; cmd.sector = sec + 1;
cmd.cyl_lo = cylinder & BYTE; cmd.cyl_lo = cylinder & BYTE;
cmd.cyl_hi = (cylinder >> 8) & BYTE; cmd.cyl_hi = (cylinder >> 8) & BYTE;
@ -1179,11 +1007,11 @@ static ssize_t w_transfer(
{ {
struct wini *wn; struct wini *wn;
iovec_t *iop, *iov_end = iov + nr_req; iovec_t *iop, *iov_end = iov + nr_req;
int n, r, s, errors, do_dma; int r, s, errors, do_dma;
unsigned long block; unsigned long block;
u32_t w_status; u32_t w_status;
u64_t dv_size; u64_t dv_size;
unsigned nbytes; unsigned int n, nbytes;
unsigned dma_buf_offset; unsigned dma_buf_offset;
ssize_t total = 0; ssize_t total = 0;
size_t addr_offset = 0; size_t addr_offset = 0;
@ -1193,11 +1021,9 @@ static ssize_t w_transfer(
wn = w_wn; wn = w_wn;
dv_size = w_dv->dv_size; dv_size = w_dv->dv_size;
#if ENABLE_ATAPI
if (w_wn->state & ATAPI) { if (w_wn->state & ATAPI) {
return atapi_transfer(do_write, position, proc_nr, iov, nr_req); return atapi_transfer(do_write, position, proc_nr, iov, nr_req);
} }
#endif
/* Check disk address. */ /* Check disk address. */
if ((unsigned)(position % SECTOR_SIZE) != 0) return(EINVAL); if ((unsigned)(position % SECTOR_SIZE) != 0) return(EINVAL);
@ -1237,8 +1063,7 @@ static ssize_t w_transfer(
} }
/* Tell the controller to transfer nbytes bytes. */ /* Tell the controller to transfer nbytes bytes. */
r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT), r = do_transfer(wn, (nbytes >> SECTOR_SHIFT), block, do_write, do_dma);
block, do_write, do_dma);
if (do_dma) if (do_dma)
start_dma(wn, do_write); start_dma(wn, do_write);
@ -1427,7 +1252,7 @@ struct command *cmd; /* Command block */
wn->w_status = STATUS_ADMBSY; wn->w_status = STATUS_ADMBSY;
w_command = cmd->command; w_command = cmd->command;
pv_set(outbyte[0], base_ctl + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0); pv_set(outbyte[0], base_ctl + REG_CTL, wn->heads >= 8 ? CTL_EIGHTHEADS : 0);
pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp); pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp);
pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count); pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count);
pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector); pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector);
@ -1642,9 +1467,7 @@ static int w_do_close(devminor_t minor)
if (w_prepare(minor) == NULL) if (w_prepare(minor) == NULL)
return(ENXIO); return(ENXIO);
w_wn->open_ct--; w_wn->open_ct--;
#if ENABLE_ATAPI
if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close(); if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close();
#endif
return(OK); return(OK);
} }
@ -1733,7 +1556,7 @@ static int w_reset(void)
for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) { for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
if (wn->base_cmd == w_wn->base_cmd) { if (wn->base_cmd == w_wn->base_cmd) {
wn->state &= ~DEAF; wn->state &= ~DEAF;
if (w_wn->irq_need_ack) { if (w_wn->native) {
/* Make sure irq is actually enabled.. */ /* Make sure irq is actually enabled.. */
sys_irqenable(&w_wn->irq_hook_id); sys_irqenable(&w_wn->irq_hook_id);
} }
@ -1755,14 +1578,13 @@ static void w_intr_wait(void)
message m; message m;
int ipc_status; int ipc_status;
if (w_wn->irq != NO_IRQ) { if (w_wn->state & IDENTIFIED) {
/* Wait for an interrupt that sets w_status to "not busy". /* Wait for an interrupt that sets w_status to "not busy".
* (w_timeout() also clears w_status.) * (w_timeout() also clears w_status.)
*/ */
while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) { while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) {
int rr; if ((r=driver_receive(ANY, &m, &ipc_status)) != OK)
if((rr=driver_receive(ANY, &m, &ipc_status)) != OK) panic("driver_receive failed: %d", r);
panic("driver_receive failed: %d", rr);
if (is_ipc_notify(ipc_status)) { if (is_ipc_notify(ipc_status)) {
switch (_ENDPOINT_P(m.m_source)) { switch (_ENDPOINT_P(m.m_source)) {
case CLOCK: case CLOCK:
@ -1776,7 +1598,7 @@ static void w_intr_wait(void)
if (r != 0) if (r != 0)
panic("sys_inb failed: %d", r); panic("sys_inb failed: %d", r);
w_wn->w_status= w_status; w_wn->w_status= w_status;
ack_irqs(m.NOTIFY_ARG); w_hw_int(m.NOTIFY_ARG);
break; break;
default: default:
/* /*
@ -1795,7 +1617,7 @@ static void w_intr_wait(void)
} }
} }
} else { } else {
/* Interrupt not yet allocated; use polling. */ /* Device not yet identified; use polling. */
(void) w_waitfor(STATUS_BSY, 0); (void) w_waitfor(STATUS_BSY, 0);
} }
} }
@ -1855,8 +1677,8 @@ int value; /* required status */
* w_waitfor_dma * * w_waitfor_dma *
*===========================================================================*/ *===========================================================================*/
static int w_waitfor_dma(mask, value) static int w_waitfor_dma(mask, value)
int mask; /* status mask */ unsigned int mask; /* status mask */
int value; /* required status */ unsigned value; /* required status */
{ {
/* Wait until controller is in the required state. Return zero on timeout. /* Wait until controller is in the required state. Return zero on timeout.
*/ */
@ -1891,13 +1713,16 @@ static void w_geometry(devminor_t minor, struct part_geom *entry)
entry->heads = 64; entry->heads = 64;
entry->sectors = 32; entry->sectors = 32;
} else { /* Return logical geometry. */ } else { /* Return logical geometry. */
entry->cylinders = wn->lcylinders; entry->cylinders = wn->cylinders;
entry->heads = wn->lheads; entry->heads = wn->heads;
entry->sectors = wn->lsectors; entry->sectors = wn->sectors;
while (entry->cylinders > 1024) {
entry->heads *= 2;
entry->cylinders /= 2;
}
} }
} }
#if ENABLE_ATAPI
/*===========================================================================* /*===========================================================================*
* atapi_open * * atapi_open *
*===========================================================================*/ *===========================================================================*/
@ -2052,7 +1877,7 @@ static int atapi_transfer(
} else { } else {
dmabytes += nbytes; dmabytes += nbytes;
while (nbytes > 0) { while (nbytes > 0) {
vir_bytes chunk = nbytes; chunk = nbytes;
if (chunk > iov->iov_size) if (chunk > iov->iov_size)
chunk = iov->iov_size; chunk = iov->iov_size;
@ -2205,9 +2030,6 @@ int do_dma;
return(OK); return(OK);
} }
#endif /* ENABLE_ATAPI */
/*===========================================================================* /*===========================================================================*
* w_ioctl * * w_ioctl *
*===========================================================================*/ *===========================================================================*/
@ -2292,24 +2114,14 @@ static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
/*===========================================================================* /*===========================================================================*
* w_hw_int * * w_hw_int *
*===========================================================================*/ *===========================================================================*/
static void w_hw_int(unsigned int irqs) static void w_hw_int(unsigned int UNUSED(irqs))
{
/* Leftover interrupt(s) received; ack it/them. */
ack_irqs(irqs);
}
/*===========================================================================*
* ack_irqs *
*===========================================================================*/
static void ack_irqs(unsigned int irqs)
{ {
/* Leftover interrupt(s) received; ack it/them. For native drives only. */
unsigned int drive; unsigned int drive;
u32_t w_status; u32_t w_status;
for (drive = 0; drive < MAX_DRIVES; drive++) { for (drive = 0; drive < MAX_DRIVES; drive++) {
if (!(wini[drive].state & IGNORING) && wini[drive].irq_need_ack && if (!(wini[drive].state & IGNORING) && wini[drive].native) {
((1L << wini[drive].irq) & irqs)) {
if (sys_inb((wini[drive].base_cmd + REG_STATUS), if (sys_inb((wini[drive].base_cmd + REG_STATUS),
&w_status) != OK) &w_status) != OK)
{ {
@ -2360,8 +2172,6 @@ static char *strerr(int e)
return str; return str;
} }
#if ENABLE_ATAPI
/*===========================================================================* /*===========================================================================*
* atapi_intr_wait * * atapi_intr_wait *
*===========================================================================*/ *===========================================================================*/
@ -2432,55 +2242,3 @@ static int atapi_intr_wait(int UNUSED(do_dma), size_t UNUSED(max))
wn->w_status |= STATUS_ADMBSY; /* Assume not done yet. */ wn->w_status |= STATUS_ADMBSY; /* Assume not done yet. */
return(r); return(r);
} }
#endif /* ENABLE_ATAPI */
#undef sys_voutb
#undef sys_vinb
static int at_voutb(pvb_pair_t *pvb, int n)
{
int s, i;
if ((s=sys_voutb(pvb,n)) == OK)
return OK;
printf("at_wini%ld: sys_voutb failed: %d pvb (%d):\n", w_instance, s, n);
for(i = 0; i < n; i++)
printf("%2d: %4x -> %4x\n", i, pvb[i].value, pvb[i].port);
panic("sys_voutb failed");
}
static int at_vinb(pvb_pair_t *pvb, int n)
{
int s, i;
if ((s=sys_vinb(pvb,n)) == OK)
return OK;
printf("at_wini%ld: sys_vinb failed: %d pvb (%d):\n", w_instance, s, n);
for(i = 0; i < n; i++)
printf("%2d: %4x\n", i, pvb[i].port);
panic("sys_vinb failed");
}
static int at_out(int line, u32_t port, u32_t value, char *typename, int type)
{
int s;
s = sys_out(port, value, type);
if(s == OK)
return OK;
printf("at_wini%ld: line %d: %s failed: %d; %x -> %x\n",
w_instance, line, typename, s, value, port);
panic("sys_out failed");
}
static int at_in(int line, u32_t port, u32_t *value, char *typename, int type)
{
int s;
s = sys_in(port, value, type);
if(s == OK)
return OK;
printf("at_wini%ld: line %d: %s failed: %d; port %x\n",
w_instance, line, typename, s, port);
panic("sys_in failed");
}

View File

@ -4,7 +4,6 @@
#define VERBOSE 0 /* display identify messages during boot */ #define VERBOSE 0 /* display identify messages during boot */
#define VERBOSE_DMA 0 /* display DMA debugging information */ #define VERBOSE_DMA 0 /* display DMA debugging information */
#define ENABLE_ATAPI 1 /* add ATAPI cd-rom support to driver */
#define ATAPI_DEBUG 0 /* To debug ATAPI code. */ #define ATAPI_DEBUG 0 /* To debug ATAPI code. */
@ -129,7 +128,6 @@
* regular LBA. * regular LBA.
*/ */
#if ENABLE_ATAPI
#define ERROR_SENSE 0xF0 /* sense key mask */ #define ERROR_SENSE 0xF0 /* sense key mask */
#define SENSE_NONE 0x00 /* no sense key */ #define SENSE_NONE 0x00 /* no sense key */
#define SENSE_RECERR 0x10 /* recovered error */ #define SENSE_RECERR 0x10 /* recovered error */
@ -156,7 +154,6 @@
#define REG_CNT_LO 4 /* low byte of cylinder number */ #define REG_CNT_LO 4 /* low byte of cylinder number */
#define REG_CNT_HI 5 /* high byte of cylinder number */ #define REG_CNT_HI 5 /* high byte of cylinder number */
#define REG_DRIVE 6 /* drive select */ #define REG_DRIVE 6 /* drive select */
#endif
#define REG_STATUS 7 /* status */ #define REG_STATUS 7 /* status */
#define STATUS_BSY 0x80 /* controller busy */ #define STATUS_BSY 0x80 /* controller busy */
@ -167,15 +164,10 @@
#define STATUS_CORR 0x04 /* correctable error occurred */ #define STATUS_CORR 0x04 /* correctable error occurred */
#define STATUS_CHECK 0x01 /* check error */ #define STATUS_CHECK 0x01 /* check error */
#if ENABLE_ATAPI
#define ATAPI_PACKETCMD 0xA0 /* packet command */ #define ATAPI_PACKETCMD 0xA0 /* packet command */
#define ATAPI_IDENTIFY 0xA1 /* identify drive */ #define ATAPI_IDENTIFY 0xA1 /* identify drive */
#define SCSI_READ10 0x28 /* read from disk */ #define SCSI_READ10 0x28 /* read from disk */
#define SCSI_SENSE 0x03 /* sense request */ #define SCSI_SENSE 0x03 /* sense request */
#endif /* ATAPI */
/* Interrupt request lines. */
#define NO_IRQ 0 /* no IRQ set yet */
#define ATAPI_PACKETSIZE 12 #define ATAPI_PACKETSIZE 12
#define SENSE_PACKETSIZE 18 #define SENSE_PACKETSIZE 18
@ -189,12 +181,12 @@
#define WAKEUP_TICKS (WAKEUP_SECS*system_hz) #define WAKEUP_TICKS (WAKEUP_SECS*system_hz)
/* Miscellaneous. */ /* Miscellaneous. */
#define MAX_DRIVES 8 #define MAX_DRIVES 4 /* max number of actual drives per instance */
#define COMPAT_DRIVES 4 #define MAX_DRIVENODES 8 /* number of drive nodes, for node numbering */
#define MAX_SECS 256 /* controller can transfer this many sectors */ #define MAX_SECS 256 /* controller can transfer this many sectors */
#define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE) #define NR_MINORS (MAX_DRIVENODES * DEV_PER_DRIVE)
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) #define NR_SUBDEVS (MAX_DRIVENODES * SUB_PER_DRIVE)
#define DELAY_USECS 1000 /* controller timeout in microseconds */ #define DELAY_USECS 1000 /* controller timeout in microseconds */
#define DELAY_TICKS 1 /* controller timeout in ticks */ #define DELAY_TICKS 1 /* controller timeout in ticks */
#define DEF_TIMEOUT_USECS 5000000L /* controller timeout in microseconds */ #define DEF_TIMEOUT_USECS 5000000L /* controller timeout in microseconds */
@ -203,18 +195,15 @@
#define INITIALIZED 0x01 /* drive is initialized */ #define INITIALIZED 0x01 /* drive is initialized */
#define DEAF 0x02 /* controller must be reset */ #define DEAF 0x02 /* controller must be reset */
#define SMART 0x04 /* drive supports ATA commands */ #define SMART 0x04 /* drive supports ATA commands */
#if ENABLE_ATAPI
#define ATAPI 0x08 /* it is an ATAPI device */ #define ATAPI 0x08 /* it is an ATAPI device */
#else
#define ATAPI 0 /* don't bother with ATAPI; optimise out */
#endif
#define IDENTIFIED 0x10 /* w_identify done successfully */ #define IDENTIFIED 0x10 /* w_identify done successfully */
#define IGNORING 0x20 /* w_identify failed once */ #define IGNORING 0x20 /* w_identify failed once */
#define NO_DMA_VAR "ata_no_dma" #define NO_DMA_VAR "ata_no_dma"
/* BIOS parameter table layout. */ #define ATA_IF_NATIVE0 (1L << 0) /* first channel is in native mode */
#define bp_cylinders(t) (t[0] | (t[1] << 8)) #define ATA_IF_NATIVE1 (1L << 2) /* second channel is in native mode */
#define bp_heads(t) (t[2])
#define bp_precomp(t) (t[5] | (t[6] << 8)) extern int sef_cb_lu_prepare(int state);
#define bp_sectors(t) (t[14]) extern int sef_cb_lu_state_isvalid(int state);
extern void sef_cb_lu_state_dump(int state);

View File

@ -40,7 +40,7 @@ then if [ -e $ACPI -a -n "`sysenv acpi`" ]
/bin/service -c up /sbin/virtio_blk -dev /dev/c0d0 -label virtio_blk_0 -args instance=0 /bin/service -c up /sbin/virtio_blk -dev /dev/c0d0 -label virtio_blk_0 -args instance=0
else else
/bin/service -c up /sbin/at_wini -dev /dev/c0d0 -label at_wini_0 /bin/service -c up /sbin/at_wini -dev /dev/c0d0 -label at_wini_0
/bin/service -cr up /sbin/at_wini -dev /dev/c1d0 -label at_wini_1 -args instance=1 /bin/service -cr up /sbin/at_wini -dev /dev/c1d0 -label at_wini_1 -args instance=1 2>/dev/null || :
fi fi
/bin/umount /proc >/dev/null /bin/umount /proc >/dev/null
fi fi

View File

@ -368,12 +368,14 @@ service at_wini
DEVIO # 21 DEVIO # 21
SDEVIO # 22 SDEVIO # 22
VDEVIO # 23 VDEVIO # 23
READBIOS # 35
; ;
pci class pci class # Match these PCI classes:
1/1 # Mass storage / IDE 1/1 # Mass storage / IDE
1/80 # Mass storage / Other (80 hex) ;
1/4 # Mass storage / RAID pci device # In addition, match these devices:
1106:3149 # VIA VT6420 RAID (1/4)
1095:3512/1095:6512 # Silicon Image SATA RAID (1/4)
1095:3114/1095:3114 # Silicon Image SATA RAID (1/80)
; ;
}; };

View File

@ -93,23 +93,9 @@
*/ */
#define NR_MEMS 16 #define NR_MEMS 16
/* Click to byte conversions (and vice versa). */
#define HCLICK_SHIFT 4 /* log2 of HCLICK_SIZE */
#define HCLICK_SIZE 16 /* hardware segment conversion magic */
#if CLICK_SIZE >= HCLICK_SIZE
#define click_to_hclick(n) ((n) << (CLICK_SHIFT - HCLICK_SHIFT))
#else
#define click_to_hclick(n) ((n) >> (HCLICK_SHIFT - CLICK_SHIFT))
#endif
#define hclick_to_physb(n) ((phys_bytes) (n) << HCLICK_SHIFT)
#define physb_to_hclick(n) ((n) >> HCLICK_SHIFT)
#define CLICK2ABS(v) ((v) << CLICK_SHIFT) #define CLICK2ABS(v) ((v) << CLICK_SHIFT)
#define ABS2CLICK(a) ((a) >> CLICK_SHIFT) #define ABS2CLICK(a) ((a) >> CLICK_SHIFT)
#define ABS -999 /* this process means absolute memory */
/* Flag bits for i_mode in the inode. */ /* Flag bits for i_mode in the inode. */
#define I_TYPE 0170000 /* this field gives inode type */ #define I_TYPE 0170000 /* this field gives inode type */
#define I_UNIX_SOCKET 0140000 /* unix domain socket */ #define I_UNIX_SOCKET 0140000 /* unix domain socket */