From: David van Moolenbroek Date: Wed, 2 Oct 2013 17:37:00 +0000 (+0200) Subject: at_wini: PCI-only now; one controller per instance X-Git-Tag: v3.3.0~542 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/dnssec-revoke.html?a=commitdiff_plain;h=6d466f941bf116c7196098a7cc85377a91ebb9a8;p=minix.git 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 --- diff --git a/drivers/at_wini/at_wini.c b/drivers/at_wini/at_wini.c index 6694b620d..df9ba4747 100644 --- a/drivers/at_wini/at_wini.c +++ b/drivers/at_wini/at_wini.c @@ -1,11 +1,8 @@ /* This file contains the device dependent part of a driver for the IBM-AT * winchester controller. Written by Adri Koppes. * - * The file contains one entry point: - * - * at_winchester_task: main entry when system is brought up - * * Changes: + * Oct 2, 2013 drop non-PCI support; one controller per instance (David) * Aug 19, 2005 ATA PCI support, supports SATA (Ben Gras) * Nov 18, 2004 moved AT disk driver to user-space (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_silent = 0; -static int w_next_drive = 0; - static u32_t system_hz; -/* The struct wini is indexed by controller first, then drive (0-3). - * Controller 0 is always the 'compatability' ide controller, at - * the fixed locations, whether present or not. - */ +/* The struct wini is indexed by drive (0-3). */ static struct wini { /* main drive struct, one entry per drive */ unsigned state; /* drive state: deaf, initialized, dead */ unsigned short w_status; /* device status register */ unsigned base_cmd; /* command base register */ unsigned base_ctl; /* control base register */ unsigned base_dma; /* dma base register */ - int dma_intseen; - unsigned irq; /* interrupt request line */ - unsigned irq_need_ack; /* irq needs to be acknowledged */ + unsigned char native; /* if set, drive is native (not compat.) */ + unsigned char lba48; /* if set, drive supports lba48 */ + 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 lba48; /* supports lba48 */ - int dma; /* supports dma */ - unsigned lcylinders; /* logical number of cylinders (BIOS) */ - 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 cylinders; /* physical number of cylinders */ + unsigned heads; /* physical number of heads */ + unsigned sectors; /* physical number of sectors per track */ 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 open_ct; /* in-use count */ 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 */ -/* IDE devices we trust are IDE devices. */ -static struct quirk -{ - 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_probe(int skip, u16_t *vidp, u16_t *didp); +static void w_init(int devind, u16_t vid, u16_t did); +static int init_params(void); static int w_do_open(devminor_t minor, int access); static struct device *w_prepare(devminor_t dev); 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, size_t addr_offset, int do_write); static void w_need_reset(void); -static void ack_irqs(unsigned int); static int w_do_close(devminor_t minor); static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t 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 int at_intr_wait(void); 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); -#if ENABLE_ATAPI 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_open(void); static void atapi_close(void); static int atapi_transfer(int do_write, u64_t position, endpoint_t 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. */ static struct blockdriver w_dtab = { @@ -209,9 +160,6 @@ static struct blockdriver w_dtab = { /* SEF functions and variables. */ static void sef_local_startup(void); 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 * @@ -252,6 +200,9 @@ static void sef_local_startup(void) static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) { /* Initialize the at_wini driver. */ + int skip, devind; + u16_t vid, did; + system_hz = sys_hz(); 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; /* 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! */ blockdriver_announce(type); @@ -272,16 +239,10 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) /*===========================================================================* * init_params * *===========================================================================*/ -static void init_params(void) +static int init_params(void) { /* This routine is called at startup to initialize the drive parameters. */ - - u16_t parv[2]; - unsigned int vector, size; - int drive, nr_drives; - struct wini *wn; - u8_t params[16]; - int s; + int drive; long wakeup_secs = WAKEUP_SECS; /* Boot variables. */ @@ -316,264 +277,177 @@ static void init_params(void) } } - if (w_instance == 0) { - /* Get the number of drives from the BIOS data area */ - 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++) { - 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); + for (drive = 0; drive < MAX_DRIVES; drive++) + wini[drive].state = IGNORING; + return (int) w_instance; } -#define ATA_IF_NOTCOMPAT1 (1L << 0) -#define ATA_IF_NOTCOMPAT2 (1L << 2) - /*===========================================================================* * init_drive * *===========================================================================*/ -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_drive(int drive, int base_cmd, int base_ctl, int base_dma, + int native, int hook) { - w->state = 0; - w->w_status = 0; - w->base_cmd = base_cmd; - w->base_ctl = base_ctl; - w->base_dma = base_dma; - if(w_pci_debug) - printf("at_wini%ld: drive %d: base_cmd 0x%x, base_ctl 0x%x, base_dma 0x%x\n", - w_instance, w-wini, w->base_cmd, w->base_ctl, w->base_dma); - w->irq = irq; - w->irq_need_ack = ack; - w->irq_hook_id = hook; - w->ldhpref = ldh_init(drive); - w->max_count = MAX_SECS << SECTOR_SHIFT; - w->lba48 = 0; - w->dma = 0; + struct wini *w; + + w = &wini[drive]; + + w->state = 0; + w->w_status = 0; + w->base_cmd = base_cmd; + w->base_ctl = base_ctl; + w->base_dma = base_dma; + if (w_pci_debug) + printf("at_wini%ld: drive %d: base_cmd 0x%x, base_ctl 0x%x, " + "base_dma 0x%x\n", w_instance, drive, w->base_cmd, w->base_ctl, + w->base_dma); + w->native = native; + w->irq_hook_id = hook; + w->ldhpref = ldh_init(drive); + w->max_count = MAX_SECS << SECTOR_SHIFT; + w->lba48 = 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) { - if(table->vendor == vid && table->device == did && - table->pci_class == bcr && - table->pci_subclass == scr && - (table->pci_interface == -1 || - table->pci_interface == interface)) { - return 1; - } - table++; - } +/*===========================================================================* + * w_probe * + *===========================================================================*/ +static int w_probe(int skip, u16_t *vidp, u16_t *didp) +{ +/* 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; - return 0; -} + pci_init(); -static void -pci_busmaster(int devind) -{ - u16_t cr; + r = pci_first_dev(&devind, vidp, didp); + if (r <= 0) + return -1; - /* Enable busmastering if necessary. */ - cr = pci_attr_r16(devind, PCI_CR); - if (!(cr & PCI_CR_MAST_EN)) { - pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN); - } + 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; - int irq, irq_hook; +/* Initialize drives on the controller that we found and reserved. Each + * controller has two channels, each of which may have up to two disks + * attached, so the maximum number of disks per controller is always four. + * In this function, we always initialize the slots for all four disks; later, + * 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 + * channels on the controller may be in native or compatibility mode. The PCI + * interface field tells us which channel is in which mode. For native + * channels, we get the IRQ and the channel's base control and command + * addresses from the PCI slot, and we manually acknowledge interrupts. For + * compatibility channels, we use the hardcoded legacy IRQs and addresses, and + * enable automatic IRQ reenabling. In both cases, we get the base DMA address + * from the PCI slot if it is there. + */ + int r, irq, native_hook, compat_hook, is_ide, nhooks; u8_t bcr, scr, interface; - u16_t vid, did; - u32_t base_dma, t3; + u16_t cr; + u32_t base_cmd, base_ctl, base_dma; - pci_init(); - for(drive = w_next_drive; drive < MAX_DRIVES; drive++) - wini[drive].state = IGNORING; - for(r = pci_first_dev(&devind, &vid, &did); r != 0; - r = pci_next_dev(&devind, &vid, &did)) { - int quirk = 0; - - /* Except class 01h (mass storage), subclass be 01h (ATA). - * Also check listed RAID controllers. - */ - bcr= pci_attr_r8(devind, PCI_BCR); - scr= pci_attr_r8(devind, PCI_SCR); - 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 */ + bcr= pci_attr_r8(devind, PCI_BCR); + scr= pci_attr_r8(devind, PCI_SCR); + interface= pci_attr_r8(devind, PCI_PIFR); - /* Found a controller. - * Programming interface register tells us more. - */ - irq = pci_attr_r8(devind, PCI_ILR); + is_ide = (bcr == PCI_BCR_MASS_STORAGE && scr == PCI_MS_IDE); - /* 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 = pci_attr_r8(devind, PCI_ILR); + base_dma = pci_attr_r32(devind, PCI_BAR_5) & PCI_BAR_IO_MASK; - 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; - - /* Primary channel not in compatability mode? */ - if (quirk || (interface & ATA_IF_NOTCOMPAT1)) { - u32_t base_cmd, base_ctl; - - 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; - if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) { - init_drive(&wini[w_next_drive], - base_cmd, base_ctl+PCI_CTL_OFF, - base_dma, irq, 1, irq_hook, 0); - init_drive(&wini[w_next_drive+1], - base_cmd, base_ctl+PCI_CTL_OFF, - base_dma, irq, 1, irq_hook, 1); - if (w_pci_debug) - printf("at_wini%ld: atapci %d: 0x%x 0x%x irq %d\n", - w_instance, devind, base_cmd, base_ctl, irq); - w_next_drive += 2; - } else printf("at_wini%ld: atapci: ignored drives on primary channel, base %x\n", w_instance, base_cmd); - } - else - { - /* Update base_dma for compatibility device */ - for (i= 0; istate & DEAF){ 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)) return(EACCES); -#endif /* Partition the drive if it's being opened for the first time, * or being opened after being closed. */ if (wn->open_ct == 0) { -#if ENABLE_ATAPI if (wn->state & ATAPI) { int r; if ((r = atapi_open()) != OK) return(r); } -#endif /* Partition the disk. */ 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, ... */ w_drive = device / DEV_PER_DRIVE; /* save drive number */ + if (w_drive >= MAX_DRIVES) return(NULL); w_wn = &wini[w_drive]; w_dv = &w_wn->part[device % DEV_PER_DRIVE]; } else if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/ w_drive = device / SUB_PER_DRIVE; + if (w_drive >= MAX_DRIVES) return(NULL); w_wn = &wini[w_drive]; w_dv = &w_wn->subpart[device % SUB_PER_DRIVE]; } 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) 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. */ wn->state |= SMART; /* Preferred CHS translation mode. */ - wn->pcylinders = id_word(1); - wn->pheads = id_word(3); - wn->psectors = id_word(6); - size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors; + wn->cylinders = id_word(1); + wn->heads = id_word(3); + wn->sectors = id_word(6); + size = (u32_t) wn->cylinders * wn->heads * wn->sectors; w= id_word(ID_CAPABILITIES); if ((w & ID_CAP_LBA) && size > 512L*1024*2) { @@ -856,20 +718,7 @@ static int w_identify(void) check_dma(wn); } - - 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, + } else if (cmd.command = ATAPI_IDENTIFY, com_simple(&cmd) == OK && w_waitfor(STATUS_DRQ, STATUS_DRQ) && !(wn->w_status & (STATUS_ERR|STATUS_WF))) { /* An ATAPI device. */ @@ -881,20 +730,13 @@ static int w_identify(void) size = 0; /* Size set later. */ check_dma(wn); -#endif } else { /* 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; - w_testing = 0; - 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; + wakeup_ticks = prev_wakeup; + w_testing = 0; + return(ERR); } /* Restore wakeup_ticks and unset testing mode. */ @@ -909,15 +751,6 @@ static int w_identify(void) 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; return(OK); } @@ -946,11 +779,7 @@ static int w_io_test(void) static char *buf; ssize_t r; -#ifdef CD_SECTOR_SIZE #define BUFSIZE CD_SECTOR_SIZE -#else -#define BUFSIZE SECTOR_SIZE -#endif STATICINIT(buf, BUFSIZE); iov.iov_addr = (vir_bytes) buf; @@ -971,7 +800,7 @@ static int w_io_test(void) w_testing = 1; /* 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); /* Switch back. */ @@ -1009,9 +838,9 @@ static int w_specify(void) if (!(wn->state & ATAPI)) { /* Specify parameters: precompensation, number of heads and sectors. */ - cmd.precomp = wn->precomp; - cmd.count = wn->psectors; - cmd.ldh = w_wn->ldhpref | (wn->pheads - 1); + cmd.precomp = 0; + cmd.count = wn->sectors; + cmd.ldh = w_wn->ldhpref | (wn->heads - 1); cmd.command = CMD_SPECIFY; /* Specify some parameters */ /* Output command block and see if controller accepts the parameters. */ @@ -1035,13 +864,12 @@ static int w_specify(void) /*===========================================================================* * do_transfer * *===========================================================================*/ -static int do_transfer(const struct wini *wn, unsigned int precomp, - unsigned int count, unsigned int sector, - unsigned int do_write, int do_dma) +static int do_transfer(const struct wini *wn, unsigned int count, + unsigned int sector, unsigned int do_write, int do_dma) { struct command cmd; unsigned int sector_high; - unsigned secspcyl = wn->pheads * wn->psectors; + unsigned secspcyl = wn->heads * wn->sectors; int do_lba48; 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; if (do_dma) { @@ -1096,8 +924,8 @@ static int do_transfer(const struct wini *wn, unsigned int precomp, } else { int cylinder, head, sec; cylinder = sector / secspcyl; - head = (sector % secspcyl) / wn->psectors; - sec = sector % wn->psectors; + head = (sector % secspcyl) / wn->sectors; + sec = sector % wn->sectors; cmd.sector = sec + 1; cmd.cyl_lo = cylinder & BYTE; cmd.cyl_hi = (cylinder >> 8) & BYTE; @@ -1179,11 +1007,11 @@ static ssize_t w_transfer( { struct wini *wn; iovec_t *iop, *iov_end = iov + nr_req; - int n, r, s, errors, do_dma; + int r, s, errors, do_dma; unsigned long block; u32_t w_status; u64_t dv_size; - unsigned nbytes; + unsigned int n, nbytes; unsigned dma_buf_offset; ssize_t total = 0; size_t addr_offset = 0; @@ -1193,11 +1021,9 @@ static ssize_t w_transfer( wn = w_wn; dv_size = w_dv->dv_size; -#if ENABLE_ATAPI if (w_wn->state & ATAPI) { return atapi_transfer(do_write, position, proc_nr, iov, nr_req); } -#endif /* Check disk address. */ if ((unsigned)(position % SECTOR_SIZE) != 0) return(EINVAL); @@ -1237,8 +1063,7 @@ static ssize_t w_transfer( } /* Tell the controller to transfer nbytes bytes. */ - r = do_transfer(wn, wn->precomp, (nbytes >> SECTOR_SHIFT), - block, do_write, do_dma); + r = do_transfer(wn, (nbytes >> SECTOR_SHIFT), block, do_write, do_dma); if (do_dma) start_dma(wn, do_write); @@ -1427,7 +1252,7 @@ struct command *cmd; /* Command block */ wn->w_status = STATUS_ADMBSY; 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[2], base_cmd + REG_COUNT, cmd->count); 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) return(ENXIO); w_wn->open_ct--; -#if ENABLE_ATAPI if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close(); -#endif return(OK); } @@ -1733,7 +1556,7 @@ static int w_reset(void) for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) { if (wn->base_cmd == w_wn->base_cmd) { wn->state &= ~DEAF; - if (w_wn->irq_need_ack) { + if (w_wn->native) { /* Make sure irq is actually enabled.. */ sys_irqenable(&w_wn->irq_hook_id); } @@ -1755,14 +1578,13 @@ static void w_intr_wait(void) message m; 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". * (w_timeout() also clears w_status.) */ while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) { - int rr; - if((rr=driver_receive(ANY, &m, &ipc_status)) != OK) - panic("driver_receive failed: %d", rr); + if ((r=driver_receive(ANY, &m, &ipc_status)) != OK) + panic("driver_receive failed: %d", r); if (is_ipc_notify(ipc_status)) { switch (_ENDPOINT_P(m.m_source)) { case CLOCK: @@ -1776,7 +1598,7 @@ static void w_intr_wait(void) if (r != 0) panic("sys_inb failed: %d", r); w_wn->w_status= w_status; - ack_irqs(m.NOTIFY_ARG); + w_hw_int(m.NOTIFY_ARG); break; default: /* @@ -1795,7 +1617,7 @@ static void w_intr_wait(void) } } } else { - /* Interrupt not yet allocated; use polling. */ + /* Device not yet identified; use polling. */ (void) w_waitfor(STATUS_BSY, 0); } } @@ -1855,8 +1677,8 @@ int value; /* required status */ * w_waitfor_dma * *===========================================================================*/ static int w_waitfor_dma(mask, value) -int mask; /* status mask */ -int value; /* required status */ +unsigned int mask; /* status mask */ +unsigned value; /* required status */ { /* 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->sectors = 32; } else { /* Return logical geometry. */ - entry->cylinders = wn->lcylinders; - entry->heads = wn->lheads; - entry->sectors = wn->lsectors; + entry->cylinders = wn->cylinders; + entry->heads = wn->heads; + entry->sectors = wn->sectors; + while (entry->cylinders > 1024) { + entry->heads *= 2; + entry->cylinders /= 2; + } } } -#if ENABLE_ATAPI /*===========================================================================* * atapi_open * *===========================================================================*/ @@ -2052,7 +1877,7 @@ static int atapi_transfer( } else { dmabytes += nbytes; while (nbytes > 0) { - vir_bytes chunk = nbytes; + chunk = nbytes; if (chunk > iov->iov_size) chunk = iov->iov_size; @@ -2205,9 +2030,6 @@ int do_dma; return(OK); } - -#endif /* ENABLE_ATAPI */ - /*===========================================================================* * w_ioctl * *===========================================================================*/ @@ -2292,24 +2114,14 @@ static int w_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, /*===========================================================================* * w_hw_int * *===========================================================================*/ -static void w_hw_int(unsigned int irqs) -{ - /* Leftover interrupt(s) received; ack it/them. */ - ack_irqs(irqs); -} - - -/*===========================================================================* - * ack_irqs * - *===========================================================================*/ -static void ack_irqs(unsigned int irqs) +static void w_hw_int(unsigned int UNUSED(irqs)) { + /* Leftover interrupt(s) received; ack it/them. For native drives only. */ unsigned int drive; u32_t w_status; for (drive = 0; drive < MAX_DRIVES; drive++) { - if (!(wini[drive].state & IGNORING) && wini[drive].irq_need_ack && - ((1L << wini[drive].irq) & irqs)) { + if (!(wini[drive].state & IGNORING) && wini[drive].native) { if (sys_inb((wini[drive].base_cmd + REG_STATUS), &w_status) != OK) { @@ -2360,8 +2172,6 @@ static char *strerr(int e) return str; } -#if ENABLE_ATAPI - /*===========================================================================* * 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. */ 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"); -} - - diff --git a/drivers/at_wini/at_wini.h b/drivers/at_wini/at_wini.h index 3385dc014..18ef3fd26 100644 --- a/drivers/at_wini/at_wini.h +++ b/drivers/at_wini/at_wini.h @@ -4,7 +4,6 @@ #define VERBOSE 0 /* display identify messages during boot */ #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. */ @@ -129,7 +128,6 @@ * regular LBA. */ -#if ENABLE_ATAPI #define ERROR_SENSE 0xF0 /* sense key mask */ #define SENSE_NONE 0x00 /* no sense key */ #define SENSE_RECERR 0x10 /* recovered error */ @@ -156,7 +154,6 @@ #define REG_CNT_LO 4 /* low byte of cylinder number */ #define REG_CNT_HI 5 /* high byte of cylinder number */ #define REG_DRIVE 6 /* drive select */ -#endif #define REG_STATUS 7 /* status */ #define STATUS_BSY 0x80 /* controller busy */ @@ -167,15 +164,10 @@ #define STATUS_CORR 0x04 /* correctable error occurred */ #define STATUS_CHECK 0x01 /* check error */ -#if ENABLE_ATAPI #define ATAPI_PACKETCMD 0xA0 /* packet command */ #define ATAPI_IDENTIFY 0xA1 /* identify drive */ #define SCSI_READ10 0x28 /* read from disk */ #define SCSI_SENSE 0x03 /* sense request */ -#endif /* ATAPI */ - -/* Interrupt request lines. */ -#define NO_IRQ 0 /* no IRQ set yet */ #define ATAPI_PACKETSIZE 12 #define SENSE_PACKETSIZE 18 @@ -185,16 +177,16 @@ #define ERR_BAD_SECTOR (-2) /* block marked bad detected */ /* Some controllers don't interrupt, the clock will wake us up. */ -#define WAKEUP_SECS 32 /* drive may be out for 31 seconds max */ +#define WAKEUP_SECS 32 /* drive may be out for 31 seconds max */ #define WAKEUP_TICKS (WAKEUP_SECS*system_hz) /* Miscellaneous. */ -#define MAX_DRIVES 8 -#define COMPAT_DRIVES 4 +#define MAX_DRIVES 4 /* max number of actual drives per instance */ +#define MAX_DRIVENODES 8 /* number of drive nodes, for node numbering */ #define MAX_SECS 256 /* controller can transfer this many sectors */ #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ -#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE) -#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) +#define NR_MINORS (MAX_DRIVENODES * DEV_PER_DRIVE) +#define NR_SUBDEVS (MAX_DRIVENODES * SUB_PER_DRIVE) #define DELAY_USECS 1000 /* controller timeout in microseconds */ #define DELAY_TICKS 1 /* controller timeout in ticks */ #define DEF_TIMEOUT_USECS 5000000L /* controller timeout in microseconds */ @@ -203,18 +195,15 @@ #define INITIALIZED 0x01 /* drive is initialized */ #define DEAF 0x02 /* controller must be reset */ #define SMART 0x04 /* drive supports ATA commands */ -#if ENABLE_ATAPI #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 IGNORING 0x20 /* w_identify failed once */ #define NO_DMA_VAR "ata_no_dma" -/* BIOS parameter table layout. */ -#define bp_cylinders(t) (t[0] | (t[1] << 8)) -#define bp_heads(t) (t[2]) -#define bp_precomp(t) (t[5] | (t[6] << 8)) -#define bp_sectors(t) (t[14]) +#define ATA_IF_NATIVE0 (1L << 0) /* first channel is in native mode */ +#define ATA_IF_NATIVE1 (1L << 2) /* second channel is in native mode */ + +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); diff --git a/drivers/ramdisk/rc b/drivers/ramdisk/rc index c26ed3c9e..d249cd501 100644 --- a/drivers/ramdisk/rc +++ b/drivers/ramdisk/rc @@ -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 else /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 /bin/umount /proc >/dev/null fi diff --git a/etc/system.conf b/etc/system.conf index 2bfd282ea..84d4d2b80 100644 --- a/etc/system.conf +++ b/etc/system.conf @@ -368,12 +368,14 @@ service at_wini DEVIO # 21 SDEVIO # 22 VDEVIO # 23 - READBIOS # 35 ; - pci class - 1/1 # Mass storage / IDE - 1/80 # Mass storage / Other (80 hex) - 1/4 # Mass storage / RAID + pci class # Match these PCI classes: + 1/1 # Mass storage / IDE + ; + 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) ; }; diff --git a/include/minix/const.h b/include/minix/const.h index a713e0549..e685e1608 100644 --- a/include/minix/const.h +++ b/include/minix/const.h @@ -93,23 +93,9 @@ */ #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 ABS2CLICK(a) ((a) >> CLICK_SHIFT) -#define ABS -999 /* this process means absolute memory */ - /* Flag bits for i_mode in the inode. */ #define I_TYPE 0170000 /* this field gives inode type */ #define I_UNIX_SOCKET 0140000 /* unix domain socket */