Index: PAO/sys/i386/apm/apm.c diff -c PAO/sys/i386/apm/apm.c:1.1.1.3 PAO/sys/i386/apm/apm.c:1.1.1.3.4.3 *** PAO/sys/i386/apm/apm.c:1.1.1.3 Fri Jul 24 19:15:06 1998 --- PAO/sys/i386/apm/apm.c Tue Dec 22 17:27:52 1998 *************** *** 4,9 **** --- 4,10 ---- * Copyright (c) 1994 UKAI, Fumitoshi. * Copyright (c) 1994-1995 by HOSOKAWA, Tatsumi * Copyright (c) 1996 Nate Williams + * Copyright (c) 1998 NAKAGAWA, Yoshihisa * * This software may be used, modified, copied, and distributed, in * both source and binary form provided that the above copyright and *************** *** 25,30 **** --- 26,32 ---- #endif /*DEVFS*/ #include #include + #include #include #include #include *************** *** 34,52 **** #include #include #include static int apm_display __P((int newstate)); ! static int apm_int __P((u_long *eax, u_long *ebx, u_long *ecx)); static void apm_resume __P((void)); /* static data */ struct apm_softc { int initialized, active; int always_halt_cpu, slow_idle_cpu; int disabled, disengaged; u_int minorversion, majorversion; u_int cs32_base, cs16_base, ds_base; ! u_int cs_limit, ds_limit; u_int cs_entry; u_int intversion; struct apmhook sc_suspend; --- 36,66 ---- #include #include #include + #ifdef NECMG + #include + #endif /* NECMG */ static int apm_display __P((int newstate)); ! static int apm_int __P((u_long *eax, u_long *ebx, u_long *ecx, u_long *edx)); static void apm_resume __P((void)); + #ifdef PC98 + static int get_batt_life_pc98 __P((u_char status)); + static int apm_get_info_pc98 __P((apm_info_t aip)); + #endif + + #define APM_FORCE_APM10_FLAG 0x02 + #define APM_NO_CLOCK_ADJUST_FLAG 0x04 + /* static data */ struct apm_softc { int initialized, active; int always_halt_cpu, slow_idle_cpu; int disabled, disengaged; + int suspending; u_int minorversion, majorversion; u_int cs32_base, cs16_base, ds_base; ! u_int cs16_limit, cs32_limit, ds_limit; u_int cs_entry; u_int intversion; struct apmhook sc_suspend; *************** *** 77,91 **** /* setup APM GDT discriptors */ static void ! setup_apm_gdt(u_int code32_base, u_int code16_base, u_int data_base, u_int code_limit, u_int data_limit) { /* setup 32bit code segment */ gdt_segs[GAPMCODE32_SEL].ssd_base = code32_base; ! gdt_segs[GAPMCODE32_SEL].ssd_limit = code_limit; /* setup 16bit code segment */ gdt_segs[GAPMCODE16_SEL].ssd_base = code16_base; ! gdt_segs[GAPMCODE16_SEL].ssd_limit = code_limit; /* setup data segment */ gdt_segs[GAPMDATA_SEL ].ssd_base = data_base; --- 91,105 ---- /* setup APM GDT discriptors */ static void ! setup_apm_gdt(u_int code32_base, u_int code16_base, u_int data_base, u_int code32_limit, u_int code16_limit, u_int data_limit) { /* setup 32bit code segment */ gdt_segs[GAPMCODE32_SEL].ssd_base = code32_base; ! gdt_segs[GAPMCODE32_SEL].ssd_limit = code32_limit; /* setup 16bit code segment */ gdt_segs[GAPMCODE16_SEL].ssd_base = code16_base; ! gdt_segs[GAPMCODE16_SEL].ssd_limit = code16_limit; /* setup data segment */ gdt_segs[GAPMDATA_SEL ].ssd_base = data_base; *************** *** 97,132 **** ssdtosd(gdt_segs + GAPMDATA_SEL , &gdt[GAPMDATA_SEL ].sd); } ! /* 48bit far pointer */ ! static struct addr48 { u_long offset; u_short segment; } apm_addr; static int apm_errno; ! __inline ! int ! apm_int(u_long *eax, u_long *ebx, u_long *ecx) ! { ! u_long cf; ! __asm __volatile(" ! pushfl ! cli ! lcall _apm_addr ! movl $0, %3 ! jnc 1f ! incl %3 ! 1: ! popfl ! " ! : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=D" (cf) ! : "0" (*eax), "1" (*ebx), "2" (*ecx) ! : "dx", "si", "memory" ! ); apm_errno = ((*eax) >> 8) & 0xff; return cf; } /* enable/disable power management */ --- 111,146 ---- ssdtosd(gdt_segs + GAPMDATA_SEL , &gdt[GAPMDATA_SEL ].sd); } ! /* 48bit far pointer. Do not staticize - used from apm_setup.s */ ! struct addr48 { u_long offset; u_short segment; } apm_addr; static int apm_errno; ! #ifdef NECMG ! # define apm_int(eax, ebx, ecx, edx) necmg_apm_int(eax, ebx, ecx) ! #else /* NECMG */ ! static int ! apm_int(u_long *eax, u_long *ebx, u_long *ecx, u_long *edx) ! { ! struct apm_bios_arg apa; ! int cf; ! ! apa.eax = *eax; ! apa.ebx = *ebx; ! apa.ecx = *ecx; ! apa.edx = *edx; ! cf = apm_bios_call(&apa); ! *eax = apa.eax; ! *ebx = apa.ebx; ! *ecx = apa.ecx; ! *edx = apa.edx; apm_errno = ((*eax) >> 8) & 0xff; return cf; } + #endif /* NECMG */ /* enable/disable power management */ *************** *** 135,141 **** { struct apm_softc *sc = &apm_softc; ! u_long eax, ebx, ecx; eax = (APM_BIOS << 8) | APM_ENABLEDISABLEPM; --- 149,155 ---- { struct apm_softc *sc = &apm_softc; ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS << 8) | APM_ENABLEDISABLEPM; *************** *** 144,163 **** else ebx = 0xffff; /* APM version 1.0 only */ ecx = enable; ! return apm_int(&eax, &ebx, &ecx); } /* Tell APM-BIOS that WE will do 1.1 and see what they say... */ static void apm_driver_version(void) { ! u_long eax, ebx, ecx; eax = (APM_BIOS << 8) | APM_DRVVERSION; ebx = 0x0; /* XXX - The APM 1.1 specification is only supported for now */ ecx = 0x0101; ! if(!apm_int(&eax, &ebx, &ecx)) apm_version = eax & 0xffff; } --- 158,179 ---- else ebx = 0xffff; /* APM version 1.0 only */ ecx = enable; ! edx = 0; ! return apm_int(&eax, &ebx, &ecx, &edx); } /* Tell APM-BIOS that WE will do 1.1 and see what they say... */ static void apm_driver_version(void) { ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS << 8) | APM_DRVVERSION; ebx = 0x0; /* XXX - The APM 1.1 specification is only supported for now */ ecx = 0x0101; ! edx = 0; ! if(!apm_int(&eax, &ebx, &ecx, &edx)) apm_version = eax & 0xffff; } *************** *** 165,189 **** static int apm_engage_disengage_pm(int engage) { ! u_long eax, ebx, ecx; eax = (APM_BIOS << 8) | APM_ENGAGEDISENGAGEPM; ebx = PMDV_ALLDEV; ecx = engage; ! return(apm_int(&eax, &ebx, &ecx)); } /* get PM event */ static u_int apm_getevent(void) { ! u_long eax, ebx, ecx; eax = (APM_BIOS << 8) | APM_GETPMEVENT; ebx = 0; ecx = 0; ! if (apm_int(&eax, &ebx, &ecx)) return PMEV_NOEVENT; return ebx & 0xffff; --- 181,207 ---- static int apm_engage_disengage_pm(int engage) { ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS << 8) | APM_ENGAGEDISENGAGEPM; ebx = PMDV_ALLDEV; ecx = engage; ! edx = 0; ! return(apm_int(&eax, &ebx, &ecx, &edx)); } /* get PM event */ static u_int apm_getevent(void) { ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS << 8) | APM_GETPMEVENT; ebx = 0; ecx = 0; ! edx = 0; ! if (apm_int(&eax, &ebx, &ecx, &edx)) return PMEV_NOEVENT; return ebx & 0xffff; *************** *** 193,205 **** static int apm_suspend_system(void) { ! u_long eax, ebx, ecx; eax = (APM_BIOS << 8) | APM_SETPWSTATE; ebx = PMDV_ALLDEV; ecx = PMST_SUSPEND; ! if (apm_int(&eax, &ebx, &ecx)) { printf("Entire system suspend failure: errcode = %ld\n", 0xff & (eax >> 8)); return 1; --- 211,224 ---- static int apm_suspend_system(void) { ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS << 8) | APM_SETPWSTATE; ebx = PMDV_ALLDEV; ecx = PMST_SUSPEND; + edx = 0; ! if (apm_int(&eax, &ebx, &ecx, &edx)) { printf("Entire system suspend failure: errcode = %ld\n", 0xff & (eax >> 8)); return 1; *************** *** 207,212 **** --- 226,248 ---- return 0; } + static int + apm_standby_system(void) + { + u_long eax, ebx, ecx, edx; + + eax = (APM_BIOS << 8) | APM_SETPWSTATE; + ebx = PMDV_ALLDEV; + ecx = PMST_STANDBY; + edx = 0; + if (apm_int(&eax, &ebx, &ecx, &edx)) { + printf("Entire system standby failure: errcode = %ld\n", + 0xff & (eax >> 8)); + return 1; + } + return 0; + } + /* Display control */ /* * Experimental implementation: My laptop machine can't handle this function *************** *** 216,227 **** static int apm_display(int newstate) { ! u_long eax, ebx, ecx; eax = (APM_BIOS << 8) | APM_SETPWSTATE; ebx = PMDV_DISP0; ecx = newstate ? PMST_APMENABLED:PMST_SUSPEND; ! if (apm_int(&eax, &ebx, &ecx)) { printf("Display off failure: errcode = %ld\n", 0xff & (eax >> 8)); return 1; --- 252,264 ---- static int apm_display(int newstate) { ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS << 8) | APM_SETPWSTATE; ebx = PMDV_DISP0; ecx = newstate ? PMST_APMENABLED:PMST_SUSPEND; ! edx = 0; ! if (apm_int(&eax, &ebx, &ecx, &edx)) { printf("Display off failure: errcode = %ld\n", 0xff & (eax >> 8)); return 1; *************** *** 229,234 **** --- 266,300 ---- return 0; } + /* + * Shutdown the system completely + * + * It does not work on some laptops. I think it works on some desktops + * that has ATX power supply. + */ + void + apm_power_off(int howto, void *dummy_arg) + { + u_long eax, ebx, ecx, edx; + + if (howto & RB_POWEROFF) { + if (!apm_softc.active) + return; + + /* wait 1sec before turning off the system power */ + DELAY(1000000); + + eax = (APM_BIOS << 8) | APM_SETPWSTATE; + ebx = PMDV_ALLDEV; + ecx = PMST_OFF; + edx = 0; + if (apm_int(&eax, &ebx, &ecx, &edx)) { + printf("Power off failure: errcode = %ld\n", + 0xff & (eax >> 8)); + } + } + } + /* APM Battery low handler */ static void *************** *** 329,334 **** --- 395,401 ---- static struct timeval suspend_time; static struct timeval diff_time; + static int apm_no_clock_adjust = 0; static int apm_default_resume(void *arg) *************** *** 337,357 **** u_int second, minute, hour; struct timeval resume_time, tmp_time; ! /* modified for adjkerntz */ ! pl = splsoftclock(); ! inittodr(0); /* adjust time to RTC */ ! microtime(&resume_time); ! tmp_time = time; /* because 'time' is volatile */ ! timevaladd(&tmp_time, &diff_time); ! time = tmp_time; ! splx(pl); ! second = resume_time.tv_sec - suspend_time.tv_sec; ! hour = second / 3600; ! second %= 3600; ! minute = second / 60; ! second %= 60; ! log(LOG_NOTICE, "resumed from suspended mode (slept %02d:%02d:%02d)\n", ! hour, minute, second); return 0; } --- 404,430 ---- u_int second, minute, hour; struct timeval resume_time, tmp_time; ! if (apm_no_clock_adjust) { ! log(LOG_NOTICE, "resumed from suspended mode\n"); ! } ! else { ! /* modified for adjkerntz */ ! pl = splsoftclock(); ! inittodr(0); /* adjust time to RTC */ ! microtime(&resume_time); ! tmp_time = time; /* because 'time' is volatile */ ! timevaladd(&tmp_time, &diff_time); ! time = tmp_time; ! splx(pl); ! second = resume_time.tv_sec - suspend_time.tv_sec; ! hour = second / 3600; ! second %= 3600; ! minute = second / 60; ! second %= 60; ! log(LOG_NOTICE, ! "resumed from suspended mode (slept %02d:%02d:%02d)\n", ! hour, minute, second); ! } return 0; } *************** *** 360,374 **** { int pl; ! pl = splsoftclock(); ! microtime(&diff_time); ! inittodr(0); ! microtime(&suspend_time); ! timevalsub(&diff_time, &suspend_time); ! splx(pl); return 0; } static void apm_processevent(void); /* --- 433,454 ---- { int pl; ! if (!apm_no_clock_adjust) { ! pl = splsoftclock(); ! microtime(&diff_time); ! inittodr(0); ! microtime(&suspend_time); ! timevalsub(&diff_time, &suspend_time); ! splx(pl); ! } return 0; } + /* + * Do not suspend immediately after the system is resumed from + * suspended mode + */ + static void apm_processevent(void); /* *************** *** 386,398 **** if (!sc) return; if (sc->initialized) { apm_execute_hook(hook[APM_HOOK_SUSPEND]); if (apm_suspend_system() == 0) apm_processevent(); ! else /* Failure, 'resume' the system again */ apm_execute_hook(hook[APM_HOOK_RESUME]); } } --- 466,518 ---- if (!sc) return; + if (sc->suspending != 0) { /* avoid reentry */ + /* PCG-505: suspend -> save-to-disk */ + if (sc->initialized) { + if (apm_suspend_system() == 0) + apm_processevent(); + } + return; + } + sc->suspending = 1; + + if (sc->initialized) { + #ifdef NECMG + int s = splhigh(); + #endif apm_execute_hook(hook[APM_HOOK_SUSPEND]); if (apm_suspend_system() == 0) + #ifdef PC98 + { + #endif apm_processevent(); ! #ifdef PC98 ! /* fail to resume on 98NOTEs with old APM BIOS. */ ! if (sc->intversion == INTVERSION(1, 0)) ! timeout((void(*)(void*))apm_resume, 0, 3 * hz); ! } ! #endif ! else { /* Failure, 'resume' the system again */ apm_execute_hook(hook[APM_HOOK_RESUME]); + } + #ifdef NECMG + splx(s); + #endif + } + } + + void + apm_standby(void) + { + struct apm_softc *sc = &apm_softc; + + if (!sc) + return; + + if (sc->initialized) { + apm_standby_system(); } } *************** *** 404,426 **** if (!sc) return; if (sc->initialized) apm_execute_hook(hook[APM_HOOK_RESUME]); } /* get APM information */ static int apm_get_info(apm_info_t aip) { struct apm_softc *sc = &apm_softc; ! u_long eax, ebx, ecx; eax = (APM_BIOS << 8) | APM_GETPWSTATUS; ebx = PMDV_ALLDEV; ecx = 0; ! if (apm_int(&eax, &ebx, &ecx)) return 1; aip->ai_acline = (ebx >> 8) & 0xff; --- 524,616 ---- if (!sc) return; + sc->suspending = 0; + if (sc->initialized) apm_execute_hook(hook[APM_HOOK_RESUME]); } /* get APM information */ + #ifdef PC98 + static inline int get_batt_life_pc98(u_char status) + { + int remain; + + switch (status) { + case 0x11: + remain = 0; break; + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + remain = status & 0x7; break; + case 0x17: + remain = 8; break; + default: + return -1; + } + return ((100*remain)/8); + } + + static int + apm_get_info_pc98(apm_info_t aip) + { + struct apm_softc *sc = &apm_softc; + u_long eax, ebx, ecx, edx; + int batt1, batt2; + + eax = (APM_BIOS << 8) | APM_GETPWSTATUS_PC98; + ebx = PMDV_ALLDEV; + ecx = 0; + edx = 0xffff; /* default to unknown battery time */ + if (apm_int(&eax, &ebx, &ecx, &edx)) + return 1; + + aip->ai_acline = ebx & 0x01; + aip->ai_batt_stat = 255; /* unknown */ + + batt1 = get_batt_life_pc98(ecx & 0xff); + batt2 = get_batt_life_pc98((ecx >> 8) & 0xff); + + if (batt1 > 0 && batt2 > 0){ + aip->ai_batt_life = (batt1 + batt2)/2; + }else if (batt1 > 0){ + aip->ai_batt_life = batt1; + }else if (batt2 > 0){ + aip->ai_batt_life = batt2; + }else{ + aip->ai_batt_life = 255; + } + + aip->ai_major = (u_int)sc->majorversion; + aip->ai_minor = (u_int)sc->minorversion; + aip->ai_status = (u_int)sc->active; + return 0; + } + #endif /*PC98*/ + static int apm_get_info(apm_info_t aip) { struct apm_softc *sc = &apm_softc; ! u_long eax, ebx, ecx, edx; + #ifdef PC98 + if (sc->intversion == INTVERSION(1, 0)){ + return apm_get_info_pc98(aip); + } + #endif eax = (APM_BIOS << 8) | APM_GETPWSTATUS; ebx = PMDV_ALLDEV; ecx = 0; + edx = 0xffff; /* default to unknown battery time */ ! if (apm_int(&eax, &ebx, &ecx, &edx)) return 1; aip->ai_acline = (ebx >> 8) & 0xff; *************** *** 441,451 **** struct apm_softc *sc = &apm_softc; if (sc->active) { ! u_long eax, ebx, ecx; eax = (APM_BIOS <<8) | APM_CPUIDLE; ! ecx = ebx = 0; ! apm_int(&eax, &ebx, &ecx); } /* * Some APM implementation halts CPU in BIOS, whenever --- 631,641 ---- struct apm_softc *sc = &apm_softc; if (sc->active) { ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS <<8) | APM_CPUIDLE; ! edx = ecx = ebx = 0; ! apm_int(&eax, &ebx, &ecx, &edx); } /* * Some APM implementation halts CPU in BIOS, whenever *************** *** 473,483 **** * necessary. */ if (sc->slow_idle_cpu && sc->active) { ! u_long eax, ebx, ecx; eax = (APM_BIOS <<8) | APM_CPUBUSY; ! ecx = ebx = 0; ! apm_int(&eax, &ebx, &ecx); } } --- 663,673 ---- * necessary. */ if (sc->slow_idle_cpu && sc->active) { ! u_long eax, ebx, ecx, edx; eax = (APM_BIOS <<8) | APM_CPUBUSY; ! edx = ecx = ebx = 0; ! apm_int(&eax, &ebx, &ecx, &edx); } } *************** *** 606,612 **** apm_event = apm_getevent(); switch (apm_event) { OPMEV_DEBUGMESSAGE(PMEV_STANDBYREQ); ! apm_suspend(); break; OPMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ); apm_suspend(); --- 796,802 ---- apm_event = apm_getevent(); switch (apm_event) { OPMEV_DEBUGMESSAGE(PMEV_STANDBYREQ); ! apm_standby(); break; OPMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ); apm_suspend(); *************** *** 624,634 **** apm_resume(); break; OPMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME); ! apm_resume(); break; OPMEV_DEBUGMESSAGE(PMEV_BATTERYLOW); apm_battery_low(); apm_suspend(); break; OPMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE); break; --- 814,830 ---- apm_resume(); break; OPMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME); ! #if 0 ! apm_resume(); /* should we call this or not? */ ! #else ! inittodr(0); /* adjust time to RTC */ ! #endif break; OPMEV_DEBUGMESSAGE(PMEV_BATTERYLOW); apm_battery_low(); + #ifdef APM_BATT_LOW_SUSPEND apm_suspend(); + #endif /* APM_BATT_LOW_SUSPEND */ break; OPMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE); break; *************** *** 655,660 **** --- 851,871 ---- { #define APM_KERNBASE KERNBASE struct apm_softc *sc = &apm_softc; + int apm_force_apm10 = 0; + int rversion, rmajorversion, rminorversion; + + #ifdef FORCE_APM10 + apm_force_apm10 = 1; + #else /* FORCE_APM10 */ + apm_force_apm10 = (dvp->id_flags & APM_FORCE_APM10_FLAG); + #endif /* FORCE_APM10 */ + + #ifdef APM_NO_CLOCK_ADJUST + apm_no_clock_adjust = 1; + #else /* APM_NO_CLOCK_ADJUST */ + apm_no_clock_adjust = (dvp->id_flags & APM_NO_CLOCK_ADJUST_FLAG); + #endif /* APM_NO_CLOCK_ADJUST */ + sc->initialized = 0; *************** *** 665,672 **** sc->cs16_base = (apm_cs16_base << 4) + APM_KERNBASE; sc->cs32_base = (apm_cs32_base << 4) + APM_KERNBASE; sc->ds_base = (apm_ds_base << 4) + APM_KERNBASE; ! sc->cs_limit = apm_cs_limit; ! sc->ds_limit = apm_ds_limit; sc->cs_entry = apm_cs_entry; /* Always call HLT in idle loop */ --- 876,886 ---- sc->cs16_base = (apm_cs16_base << 4) + APM_KERNBASE; sc->cs32_base = (apm_cs32_base << 4) + APM_KERNBASE; sc->ds_base = (apm_ds_base << 4) + APM_KERNBASE; ! sc->cs32_limit = apm_cs32_limit - 1; ! if (apm_cs16_limit == 0) ! apm_cs16_limit == apm_cs32_limit; ! sc->cs16_limit = apm_cs16_limit - 1; ! sc->ds_limit = apm_ds_limit - 1; sc->cs_entry = apm_cs_entry; /* Always call HLT in idle loop */ *************** *** 684,691 **** printf("apm: Code entry 0x%08x, Idling CPU %s, Management %s\n", sc->cs_entry, is_enabled(sc->slow_idle_cpu), is_enabled(!sc->disabled)); ! printf("apm: CS_limit=0x%x, DS_limit=0x%x\n", ! sc->cs_limit, sc->ds_limit); #endif /* APM_DEBUG */ #if 0 --- 898,905 ---- printf("apm: Code entry 0x%08x, Idling CPU %s, Management %s\n", sc->cs_entry, is_enabled(sc->slow_idle_cpu), is_enabled(!sc->disabled)); ! printf("apm: CS32_limit=0x%x, CS16_limit=0x%x, DS_limit=0x%x\n", ! (u_short)sc->cs32_limit, (u_short)sc->cs16_limit, (u_short)sc->ds_limit); #endif /* APM_DEBUG */ #if 0 *************** *** 696,731 **** /* setup GDT */ setup_apm_gdt(sc->cs32_base, sc->cs16_base, sc->ds_base, ! sc->cs_limit, sc->ds_limit); /* setup entry point 48bit pointer */ apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL); apm_addr.offset = sc->cs_entry; ! #ifdef FORCE_APM10 ! apm_version = 0x100; ! sc->majorversion = 1; ! sc->minorversion = 0; ! sc->intversion = INTVERSION(sc->majorversion, sc->minorversion); ! printf("apm: running in APM 1.0 compatible mode\n"); ! #else ! /* Try to kick bios into 1.1 or greater mode */ ! apm_driver_version(); sc->minorversion = ((apm_version & 0x00f0) >> 4) * 10 + ((apm_version & 0x000f) >> 0); sc->majorversion = ((apm_version & 0xf000) >> 12) * 10 + ((apm_version & 0x0f00) >> 8); ! sc->intversion = INTVERSION(sc->majorversion, sc->minorversion); ! #ifdef APM_DEBUG ! if (sc->intversion >= INTVERSION(1, 1)) ! printf("apm: Engaged control %s\n", is_enabled(!sc->disengaged)); #endif ! ! printf("apm: found APM BIOS version %d.%d\n", ! sc->majorversion, sc->minorversion); ! #endif /* FORCE_APM10 */ #ifdef APM_DEBUG printf("apm: Slow Idling CPU %s\n", is_enabled(sc->slow_idle_cpu)); --- 910,990 ---- /* setup GDT */ setup_apm_gdt(sc->cs32_base, sc->cs16_base, sc->ds_base, ! sc->cs32_limit, sc->cs16_limit, sc->ds_limit); /* setup entry point 48bit pointer */ apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL); apm_addr.offset = sc->cs_entry; ! rversion = apm_version; ! ! #ifdef PC98 ! if (rversion & 0x00f0){ ! rminorversion = rversion & 0x000f; ! }else{ ! rminorversion = 0; ! } ! rmajorversion = ((rversion & 0xf000) >> 12) * 10 + ! ((rversion & 0x0f00) >> 8); ! sc->minorversion = ((apm_version & 0x00f0) >> 4) * 10 + ((apm_version & 0x000f) >> 0); sc->majorversion = ((apm_version & 0xf000) >> 12) * 10 + ((apm_version & 0x0f00) >> 8); ! sc->intversion = INTVERSION(1, 0); ! if (rmajorversion >= 1 && rminorversion >= 1) { ! apm_driver_version(); ! sc->intversion = INTVERSION(1, 1); ! } ! printf("apm: found APM BIOS version %d.%d\n", ! sc->majorversion, sc->minorversion); ! #else ! rminorversion = ((rversion & 0x00f0) >> 4) * 10 + ! ((rversion & 0x000f) >> 0); ! rmajorversion = ((rversion & 0xf000) >> 12) * 10 + ! ((rversion & 0x0f00) >> 8); ! ! if (apm_force_apm10) { ! apm_version = 0x100; ! sc->majorversion = 1; ! sc->minorversion = 0; ! sc->intversion = INTVERSION(1, 0); ! printf("apm: running in APM 1.0 compatible mode\n"); ! } ! else { ! if (rmajorversion >= 1 && rminorversion >= 1) { ! apm_driver_version(); ! } ! sc->minorversion = ((apm_version & 0x00f0) >> 4) * 10 + ! ((apm_version & 0x000f) >> 0); ! sc->majorversion = ((apm_version & 0xf000) >> 12) * 10 + ! ((apm_version & 0x0f00) >> 8); ! ! if ((sc->majorversion == 1 && sc->minorversion == 0 ! && rmajorversion >= 1 && rminorversion >= 1) ! || sc->majorversion > 10 /* for broken APM 1.1 */ ! ) { ! apm_version = 0x100; ! sc->majorversion = 1; ! sc->minorversion = 0; ! sc->intversion = INTVERSION(1, 0); ! printf("apm: running in APM 1.0 compatible mode\n"); ! } ! else { ! sc->intversion = ! INTVERSION(sc->majorversion, sc->minorversion); #ifdef APM_DEBUG ! if (sc->intversion >= INTVERSION(1, 1)) { ! printf("apm: Engaged control %s\n", ! is_enabled(!sc->disengaged)); ! } #endif ! printf("apm: found APM BIOS version %d.%d\n", ! sc->majorversion, sc->minorversion); ! } ! } ! #endif /* PC98 */ #ifdef APM_DEBUG printf("apm: Slow Idling CPU %s\n", is_enabled(sc->slow_idle_cpu)); *************** *** 752,772 **** } } ! /* default suspend hook */ ! sc->sc_suspend.ah_fun = apm_default_suspend; ! sc->sc_suspend.ah_arg = sc; ! sc->sc_suspend.ah_name = "default suspend"; ! sc->sc_suspend.ah_order = APM_MAX_ORDER; ! ! /* default resume hook */ ! sc->sc_resume.ah_fun = apm_default_resume; ! sc->sc_resume.ah_arg = sc; ! sc->sc_resume.ah_name = "default resume"; ! sc->sc_resume.ah_order = APM_MIN_ORDER; ! ! apm_hook_establish(APM_HOOK_SUSPEND, &sc->sc_suspend); ! apm_hook_establish(APM_HOOK_RESUME , &sc->sc_resume); apm_event_enable(); sc->initialized = 1; --- 1011,1043 ---- } } ! /* default suspend hook */ ! sc->sc_suspend.ah_fun = apm_default_suspend; ! sc->sc_suspend.ah_arg = sc; ! sc->sc_suspend.ah_name = "default suspend"; ! sc->sc_suspend.ah_order = APM_MAX_ORDER; ! ! /* default resume hook */ ! sc->sc_resume.ah_fun = apm_default_resume; ! sc->sc_resume.ah_arg = sc; ! sc->sc_resume.ah_name = "default resume"; ! sc->sc_resume.ah_order = APM_MIN_ORDER; ! ! apm_hook_establish(APM_HOOK_SUSPEND, &sc->sc_suspend); ! apm_hook_establish(APM_HOOK_RESUME , &sc->sc_resume); ! ! #ifndef NECMG ! at_shutdown(apm_power_off, NULL, SHUTDOWN_POWER_OFF); ! #else /* NECMG */ ! at_shutdown(necmg_cpu_poweroff, NULL, SHUTDOWN_POWER_OFF); ! #endif /* NECMG */ + #ifdef NECMG + /* + * apm_event_enable() do nothing if sc->initialized = 0. + */ + sc->initialized = 1; + #endif /* NECMG */ apm_event_enable(); sc->initialized = 1; *************** *** 816,822 **** break; case APMIO_GETINFO: if (apm_get_info((apm_info_t)addr)) ! error = ENXIO; break; case APMIO_ENABLE: apm_event_enable(); --- 1087,1093 ---- break; case APMIO_GETINFO: if (apm_get_info((apm_info_t)addr)) ! error = ENODEV; break; case APMIO_ENABLE: apm_event_enable(); *************** *** 833,839 **** case APMIO_DISPLAY: newstate = *(int *)addr; if (apm_display(newstate)) ! error = ENXIO; break; default: error = EINVAL; --- 1104,1110 ---- case APMIO_DISPLAY: newstate = *(int *)addr; if (apm_display(newstate)) ! error = ENODEV; break; default: error = EINVAL; *************** *** 854,860 **** dev = makedev(CDEV_MAJOR,0); cdevsw_add(&dev,&apm_cdevsw,NULL); apm_devsw_installed = 1; ! } } SYSINIT(apmdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,apm_drvinit,NULL) --- 1125,1134 ---- dev = makedev(CDEV_MAJOR,0); cdevsw_add(&dev,&apm_cdevsw,NULL); apm_devsw_installed = 1; ! #ifdef NECMG ! necmg_apm_init(); ! #endif /* !NECMG */ ! } } SYSINIT(apmdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,apm_drvinit,NULL) Index: PAO/sys/i386/apm/apm_setup.h diff -c PAO/sys/i386/apm/apm_setup.h:1.1.1.2 PAO/sys/i386/apm/apm_setup.h:1.1.1.2.8.1 *** PAO/sys/i386/apm/apm_setup.h:1.1.1.2 Sun Apr 5 07:08:57 1998 --- PAO/sys/i386/apm/apm_setup.h Tue Dec 22 17:19:54 1998 *************** *** 10,16 **** * * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * ! * $Id: apm_setup.h,v 1.4.8.1 1997/11/04 19:02:15 nate Exp $ */ extern u_long apm_version; --- 10,16 ---- * * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * ! * $Id: apm_setup.h,v 1.9 1998/06/03 01:59:33 msmith Exp $ */ extern u_long apm_version; *************** *** 18,24 **** extern u_short apm_cs32_base; extern u_short apm_cs16_base; extern u_short apm_ds_base; ! extern u_short apm_cs_limit; extern u_short apm_ds_limit; extern u_short apm_flags; extern u_short kernelbase; --- 18,27 ---- extern u_short apm_cs32_base; extern u_short apm_cs16_base; extern u_short apm_ds_base; ! extern u_short apm_cs32_limit; ! extern u_short apm_cs16_limit; extern u_short apm_ds_limit; extern u_short apm_flags; extern u_short kernelbase; + + int apm_bios_call __P((struct apm_bios_arg *)); Index: PAO/sys/i386/apm/apm_setup.s diff -c PAO/sys/i386/apm/apm_setup.s:1.1.1.2 PAO/sys/i386/apm/apm_setup.s:1.1.1.2.8.1 *** PAO/sys/i386/apm/apm_setup.s:1.1.1.2 Sun Apr 5 07:08:58 1998 --- PAO/sys/i386/apm/apm_setup.s Tue Dec 22 17:19:55 1998 *************** *** 1,5 **** --- 1,6 ---- /* * Copyright (C) 1994 by HOSOKAWA, Tatsumi + * Copyright (C) 1997 by Poul-Henning Kamp * * This software may be used, modified, copied, distributed, and sold, * in both source and binary form provided that the above copyright and *************** *** 10,16 **** * * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * ! * $Id: apm_setup.s,v 1.7.2.1 1997/11/04 19:02:17 nate Exp $ */ #include "apm.h" --- 11,17 ---- * * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * ! * $Id: apm_setup.s,v 1.13 1998/06/03 01:59:34 msmith Exp $ */ #include "apm.h" *************** *** 58,65 **** .globl _apm_ds_base .word 0 ! _apm_cs_limit: ! .globl _apm_cs_limit .word 0 _apm_ds_limit: --- 59,70 ---- .globl _apm_ds_base .word 0 ! _apm_cs32_limit: ! .globl _apm_cs32_limit ! .word 0 ! ! _apm_cs16_limit: ! .globl _apm_cs16_limit .word 0 _apm_ds_limit: *************** *** 168,177 **** shrl $16, %ecx movw %cx, PADDR(_apm_cs32_base) movw %dx, PADDR(_apm_ds_base) ! movw %si, PADDR(_apm_cs_limit) shrl $16, %esi movw %si, PADDR(_apm_ds_limit) movw %di, PADDR(_apm_flags) ret #endif NAPM > 0 --- 173,216 ---- shrl $16, %ecx movw %cx, PADDR(_apm_cs32_base) movw %dx, PADDR(_apm_ds_base) ! movw %si, PADDR(_apm_cs32_limit) shrl $16, %esi movw %si, PADDR(_apm_ds_limit) movw %di, PADDR(_apm_flags) + ret + + .text + .align 2 + .globl _apm_bios_call + _apm_bios_call: + pushl %ebp + movl 8(%esp),%ebp + pushl %esi + pushl %edi + pushl %ebx + movl 20(%ebp),%edi + movl 16(%ebp),%esi + movl 12(%ebp),%edx + movl 8(%ebp),%ecx + movl 4(%ebp),%ebx + movl 0(%ebp),%eax + pushl %ebp + lcall _apm_addr + popl %ebp + movl %eax,0(%ebp) + jc 1f + xorl %eax,%eax + jz 2f + 1: movl $1, %eax + 2: movl %ebx,4(%ebp) + movl %ecx,8(%ebp) + movl %edx,12(%ebp) + movl %esi,16(%ebp) + movl %edi,20(%ebp) + popl %ebx + popl %edi + popl %esi + popl %ebp ret #endif NAPM > 0 Index: PAO/sys/i386/conf/BOOTFLP_PAO diff -c /dev/null PAO/sys/i386/conf/BOOTFLP_PAO:1.1.8.1 *** /dev/null Fri Dec 25 10:50:26 1998 --- PAO/sys/i386/conf/BOOTFLP_PAO Sun Dec 6 07:46:20 1998 *************** *** 0 **** --- 1,258 ---- + # + # Sample Laptop Configuration + # for lenlen.ntc.keio.ac.jp (Toshiba Libretto 50CT) + # Tatsumi Hosokawa + # + + machine "i386" + cpu "I386_CPU" + cpu "I486_CPU" + cpu "I586_CPU" + cpu "I686_CPU" + ident BOOTFLP_PAO + maxusers 10 + + options MATH_EMULATE #Support for x87 emulation + options INET #InterNETworking + options FFS #Berkeley Fast Filesystem + options NFS #Network Filesystem + options MFS #Memory Filesystem + options MSDOSFS #MSDOS Filesystem + options "CD9660" #ISO 9660 Filesystem + options PROCFS #Process filesystem + options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] + options SCSI_DELAY=15 #Be pessimistic about Joe SCSI device + options BOUNCE_BUFFERS #include support for DMA bounce buffers + options UCONSOLE #Allow users to grab the console + options FAILSAFE #Be conservative + options USERCONFIG #boot -c editor + options VISUAL_USERCONFIG #visual boot -c editor + + # If your laptop have not had Windoze95-Ready BIOS, please update it. + # Such old BIOS'es sometimes have critical bugs at 32-bit protected + # mode APM BIOS interface (which have not used by Windoze 3.1). + + # PC-card suspend/resume support (experimental) + options APM_PCCARD_RESUME + options PCIC_RESUME_RESET + + # Keep power for serial cards when the system suspends + # (If your machine hangs up when you try to suspend the system with + # FAX/Modem PCMCIA card, uncomment this option). + #options SIO_SUSP_KEEP_PWR + + # Detach SCSI devices when the SCSI card is removed + options SCSI_DETACH + + # Detach ATAPI devices when the ATA card is removed + options ATAPI_DETACH + + # Japanese version of WaveLAN PCMCIA uses 2.4GHz band instead of 915MHz + # band that US version uses. If you want to use Japanese version of + # WaveLAN, uncomment this line, or edit the corresponding config entry + # of /etc/pccard.conf. + #options "WAVELAN_PCMCIA_24" + + # Suspend the system when the battery status is "Low" + #options "APM_BATT_LOW_SUSPEND" + + # If you want to use NTP on laptop machines, uncomment the following + # option. Current APM implementation affects NTP client. + #options "APM_NO_CLOCK_ADJUST" + + # For Win98 BIOS of ThinkPad options + #options "APM_TP_WIN98BIOS" + + # Some X-servers cannot survive suspend/resume on laptop. + # This option kicks her when the system is resumed from suspended mode. + #options SYSCONS_VTY_RESUME + + + config kernel root on wd0 + + controller isa0 + #controller eisa0 + controller pci0 + + # Dont remove these two lines! + pseudo-device card 1 + + # You must use "flags 0x1" when you don't hear any negotiation noise(?) + # if you use modem card, or pccardd doesn't read cis tuple, tell you + # 'No card in database for"(null)"("(null)")' in case of Cirrus Logic's + # pcic is your PC. + #device pcic0 at isa? port 0x3e0 flags 0x1 irq 11 vector pcicintr + device pcic0 at isa? port 0x3e0 irq 11 vector pcicintr + device pcic0 at isa? port 0x3e4 irq 11 vector pcicintr + device pcic1 at isa? port 0x3e2 # for HiNote Ultra II + device pcic1 at isa? port 0x3e4 # for Chandra II + + controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr + disk fd0 at fdc0 drive 0 + + controller fdc1 at isa? disable port "IO_YEFDC" bio irq 6 vector fdintr + disk fd1 at fdc1 drive 0 + options FDC_YE + + options "CMD640" # work around CMD640 chip deficiency + controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr + disk wd0 at wdc0 drive 0 + + controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr + disk wd1 at wdc1 drive 0 + + controller wdc2 at isa? disable port "IO_WD2" bio irq 15 vector wdintr + disk wd2 at wdc2 drive 0 + + controller wdc3 at isa? disable port "IO_WD2" bio irq 15 vector wdintr + disk wd3 at wdc3 drive 0 + + options ATAPI #Enable ATAPI support for IDE bus + options ATAPI_STATIC #Don't do it as an LKM + device wcd0 #IDE CD-ROM + #device wfd0 #IDE floppy (LS-120) + + # A single entry for any of these controllers (ncr, ahb, ahc, amd) is + # sufficient for any number of installed devices. + + #controller ncr0 + #controller amd0 + #controller ahb0 + #controller ahc0 + #controller dpt0 + #controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr + #controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr + #controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr + controller aic0 at isa? port 0x340 bio irq 11 vector aicintr + #controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr + #controller nca1 at isa? port 0x350 bio irq 5 vector ncaintr + #controller sea0 at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr + controller spc0 at isa? port 0x320 bio irq 11 iomem 0xd0000 flags 0x01 vector spcintr + + # Future domain and Q-logic PC-card SCSI drivers + # ported from NetBSD/pc98 (based on NetBSD 1.2) + options SCSI_LOW # XXX: for ncv? and stg? driver + controller ncv0 at isa? port 0x320 bio irq 5 vector ncvintr + controller stg0 at isa? port 0x320 bio irq 5 vector stgintr + + #options DPT_MEASURE_PERFORMANCE # Required by DPT driver?? + #options DPT_VERIFY_HINTR # Some hardware must have it! + #options DPT_TRACK_CCB_STATES # Some hardware must have it! + #options DPT_HANDLE_TIMEOUTS # Some hardware must have it! + #options DPT_TIMEOUT_FACTOR=4 # Some hardware needs more + + controller scbus0 + + device sd0 + + #device od0 #See LINT for possible `od' options. + + #device st0 + + device cd0 #Only need one of these, the code dynamically grows + + #device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr + #device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr + + #controller matcd0 at isa? port 0x230 bio + + #device scd0 at isa? port 0x230 bio + + # syscons is the default console driver, resembling an SCO console + device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr + # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver + #device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint + #options XSERVER # support for X server + #options FAT_CURSOR # start with block cursor + # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines + #options PCVT_SCANSET=2 # IBM keyboards are non-std + + # Mandatory, don't remove + device npx0 at isa? port "IO_NPX" flags 0x1 irq 13 vector npxintr + + # + # Laptop support (see LINT for more options) + # + device apm0 at isa? # Advanced Power Management + options APM_BROKEN_STATCLOCK # Workaround some buggy APM BIOS + + device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr + device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr + device sio2 at isa? disable port "IO_COM3" tty irq 5 vector siointr + device sio3 at isa? disable port "IO_COM4" tty irq 9 vector siointr + device sio4 at isa? disable port "IO_COM3" tty irq 5 vector siointr + + device lpt0 at isa? port? tty irq 7 vector lptintr + device lpt1 at isa? port? tty + #device mse0 at isa? port 0x23c tty irq 5 vector mseintr + + device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr + + # Order is important here due to intrusive probes, do *not* alphabetize + # this list of network interfaces until the probes have been fixed. + # Right now it appears that the ie0 must be probed before ep0. See + # revision 1.20 of this file. + #device de0 + #device fxp0 + #device tx0 + #device vx0 + + device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr + device ed1 at isa? disable port 0x300 net irq 10 iomem 0xd8000 vector edintr + #device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector ieintr + device ep0 at isa? port 0x300 net irq 10 vector epintr + device ep1 at isa? disable port 0x300 net irq 10 vector epintr + #device ex0 at isa? port? net irq? vector exintr + device fe0 at isa? port 0x300 net irq 10 vector feintr + device fe1 at isa? disable port 0x300 net irq 10 vector feintr + #device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr + #device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr + device sn0 at isa? port 0x300 net irq 10 vector snintr + device sn1 at isa? disable port 0x300 net irq 10 vector snintr + #device wlp0 at isa? port 0x300 net irq 11 vector wlpintr + #device wlp1 at isa? disable port 0x300 net irq 11 vector wlpintr + #device cs0 at isa? disable port 0x300 net irq ? vector csintr + #device cnw0 at isa? port 0x300 net irq 5 vector cnwintr + #device cnw1 at isa? disable port 0x300 net irq 5 vector cnwintr + + # do not enable ze0 and zp0 (these devices are obsolete) + ##device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr + ##device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr + + # IBM Smart Capture PCMCIA card + #device scc0 + #device scc1 + + # Hitachi microcomputer system Speach Synthesizer card + #device hss0 + #device hss1 + + # PCMCIA Joystick + #device joy0 at isa? port "IO_GAME" + + pseudo-device loop + pseudo-device ether + #pseudo-device log + #pseudo-device sl 1 + # DHCP uses BPF (Berkeley Packet Filter) + #pseudo-device bpfilter 4 + # ijppp uses tun instead of ppp device + #pseudo-device ppp 1 + #pseudo-device vn 1 + #pseudo-device tun 1 + pseudo-device pty 16 + pseudo-device gzip # Exec gzipped a.out's + + #options DDB + + # KTRACE enables the system-call tracing facility ktrace(2). + # This adds 4 KB bloat to your kernel, and slightly increases + # the costs of each syscall. + #options KTRACE #kernel tracing + + # This provides support for System V shared memory. + # + #options SYSVSHM + #options SYSVSEM + #options SYSVMSG + Index: PAO/sys/i386/conf/LINT diff -c PAO/sys/i386/conf/LINT:1.1.1.4 PAO/sys/i386/conf/LINT:1.1.1.4.2.1 *** PAO/sys/i386/conf/LINT:1.1.1.4 Sat Dec 5 05:35:54 1998 --- PAO/sys/i386/conf/LINT Sun Dec 6 07:46:22 1998 *************** *** 665,674 **** options SLOW_VGA # do byte-wide i/o's to TS and GDC regs options SC_HISTORY_SIZE=200 # number of history buffer lines options SC_DISABLE_REBOOT # disable reboot key sequence - # Try the following option, if the mouse pointer is not drawn correctly - # or font does not seem to be loaded properly. May case flicker on - # some systems. - #options SC_ALT_SEQACCESS # # `flags' for sc0: --- 665,670 ---- Index: PAO/sys/i386/conf/Makefile.kit diff -c /dev/null PAO/sys/i386/conf/Makefile.kit:1.1.4.1 *** /dev/null Fri Dec 25 10:50:27 1998 --- PAO/sys/i386/conf/Makefile.kit Sun Dec 6 07:46:24 1998 *************** *** 0 **** --- 1,41 ---- + # $Id: Makefile.kit,v 1.1.4.1 1998/12/05 22:46:24 itojun Exp $ + # Tatsumi Hosokawa + + all: PAO BOOTFLP_PAO + + PAO: PAO_ALL + sed \ + -e 's/device\([ ]*\)hss/#device\1hss/' \ + -e 's/device\([ ]*\)scc/#device\1scc/' \ + -e 's/device\([ ]*\)wlp/#device\1wlp/' \ + -e 's/device\([ ]*\)cnw/#device\1cnw/' \ + -e 's/ident\([ ]*\)PAO_ALL/ident\1PAO/' \ + < PAO_ALL > PAO + + # CAUTION: Don't remove "device apm0" from BOOTFLP_PAO! + # Typical default value of power management BIOS setup force the machine + # to suspend without typing the keys for minutes (this condition should + # happen if you select many distribution files or install from anonymous + # FTP site over slow links). + + BOOTFLP_PAO: PAO + sed \ + -e 's/device\([ ]*\)wfd/#device\1wfd/' \ + -e 's/device\([ ]*\)od/#device\1od/' \ + -e 's/device\([ ]*\)st/#device\1st/' \ + -e 's/device\([ ]*\)joy/#device\1joy/' \ + -e 's/pseudo-device\([ ]*\)log/#pseudo-device\1log/' \ + -e 's/pseudo-device\([ ]*\)bpfilter/#pseudo-device\1bpfilter/' \ + -e 's/pseudo-device\([ ]*\)vn/#pseudo-device\1vn/' \ + -e 's/pseudo-device\([ ]*\)tun/#pseudo-device\1tun/' \ + -e 's/pseudo-device\([ ]*\)sl/#pseudo-device\1sl/' \ + -e 's/options\([ ]*\)DDB/#options\1DDB/' \ + -e 's/options\([ ]*\)SYSVSHM/#options\1SYSVSHM/' \ + -e 's/options\([ ]*\)SYSVSEM/#options\1SYSVSEM/' \ + -e 's/options\([ ]*\)SYSVMSG/#options\1SYSVMSG/' \ + -e 's/tape\([ ]*\)ft/#tape\1ft/' \ + -e 's/ident\([ ]*\)PAO/ident\1BOOTFLP_PAO/' \ + < PAO > BOOTFLP_PAO + + clean: + rm -f PAO BOOTFLP_PAO BOOTMFS Index: PAO/sys/i386/conf/PAO_ALL diff -c /dev/null PAO/sys/i386/conf/PAO_ALL:1.1.8.2 *** /dev/null Fri Dec 25 10:50:28 1998 --- PAO/sys/i386/conf/PAO_ALL Wed Dec 23 15:22:42 1998 *************** *** 0 **** --- 1,261 ---- + # + # Sample Laptop Configuration + # for lenlen.ntc.keio.ac.jp (Toshiba Libretto 50CT) + # Tatsumi Hosokawa + # + + machine "i386" + cpu "I386_CPU" + cpu "I486_CPU" + cpu "I586_CPU" + cpu "I686_CPU" + ident PAO_ALL + maxusers 10 + + options MATH_EMULATE #Support for x87 emulation + options INET #InterNETworking + options FFS #Berkeley Fast Filesystem + options NFS #Network Filesystem + options MFS #Memory Filesystem + options MSDOSFS #MSDOS Filesystem + options "CD9660" #ISO 9660 Filesystem + options PROCFS #Process filesystem + options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] + options SCSI_DELAY=15 #Be pessimistic about Joe SCSI device + options BOUNCE_BUFFERS #include support for DMA bounce buffers + options UCONSOLE #Allow users to grab the console + options FAILSAFE #Be conservative + options USERCONFIG #boot -c editor + options VISUAL_USERCONFIG #visual boot -c editor + + # If your laptop have not had Windoze95-Ready BIOS, please update it. + # Such old BIOS'es sometimes have critical bugs at 32-bit protected + # mode APM BIOS interface (which have not used by Windoze 3.1). + + # PC-card suspend/resume support (experimental) + options APM_PCCARD_RESUME + options PCIC_RESUME_RESET + + # Keep power for serial cards when the system suspends + # (If your machine hangs up when you try to suspend the system with + # FAX/Modem PCMCIA card, uncomment this option). + #options SIO_SUSP_KEEP_PWR + + # Detach SCSI devices when the SCSI card is removed + options SCSI_DETACH + + # Detach ATAPI devices when the ATA card is removed + options ATAPI_DETACH + + # Japanese version of WaveLAN PCMCIA uses 2.4GHz band instead of 915MHz + # band that US version uses. If you want to use Japanese version of + # WaveLAN, uncomment this line, or edit the corresponding config entry + # of /etc/pccard.conf. + #options "WAVELAN_PCMCIA_24" + + # Suspend the system when the battery status is "Low" + #options "APM_BATT_LOW_SUSPEND" + + # If you want to use NTP on laptop machines, uncomment the following + # option. Current APM implementation affects NTP client. + #options "APM_NO_CLOCK_ADJUST" + + # For Win98 BIOS of ThinkPad options + #options "APM_TP_WIN98BIOS" + + # Some X-servers cannot survive suspend/resume on laptop. + # This option kicks her when the system is resumed from suspended mode. + #options SYSCONS_VTY_RESUME + + + config kernel root on wd0 + + controller isa0 + #controller eisa0 + controller pci0 + + # Dont remove these two lines! + pseudo-device card 1 + + # You must use "flags 0x1" when you don't hear any negotiation noise(?) + # if you use modem card, or pccardd doesn't read cis tuple, tell you + # 'No card in database for"(null)"("(null)")' in case of Cirrus Logic's + # pcic is your PC. + #device pcic0 at isa? port 0x3e0 flags 0x1 irq 11 vector pcicintr + device pcic0 at isa? port 0x3e0 irq 11 vector pcicintr + device pcic0 at isa? port 0x3e4 irq 11 vector pcicintr + device pcic1 at isa? port 0x3e2 # for HiNote Ultra II + device pcic1 at isa? port 0x3e4 # for Chandra II + + controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr + disk fd0 at fdc0 drive 0 + + controller fdc1 at isa? disable port "IO_YEFDC" bio irq 6 vector fdintr + disk fd1 at fdc1 drive 0 + options FDC_YE + + options "CMD640" # work around CMD640 chip deficiency + controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr + disk wd0 at wdc0 drive 0 + + controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr + disk wd1 at wdc1 drive 0 + + controller wdc2 at isa? disable port "IO_WD2" bio irq 15 vector wdintr + disk wd2 at wdc2 drive 0 + + controller wdc3 at isa? disable port "IO_WD2" bio irq 15 vector wdintr + disk wd3 at wdc3 drive 0 + + options ATAPI #Enable ATAPI support for IDE bus + options ATAPI_STATIC #Don't do it as an LKM + device wcd0 #IDE CD-ROM + device wfd0 #IDE floppy (LS-120) + + # A single entry for any of these controllers (ncr, ahb, ahc, amd) is + # sufficient for any number of installed devices. + + #controller ncr0 + #controller amd0 + #controller ahb0 + #controller ahc0 + #controller dpt0 + #controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr + #controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr + #controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr + controller aic0 at isa? port 0x340 bio irq 11 vector aicintr + #controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr + #controller nca1 at isa? port 0x350 bio irq 5 vector ncaintr + controller nin0 at isa? port 0x280 bio irq 5 vector ninintr + #controller sea0 at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr + controller spc0 at isa? port 0x320 bio irq 11 iomem 0xd0000 flags 0x01 vector spcintr + + # Future domain and Q-logic PC-card SCSI drivers + # ported from NetBSD/pc98 (based on NetBSD 1.2) + options SCSI_LOW # XXX: for ncv? and stg? driver + controller ncv0 at isa? port 0x320 bio irq 5 vector ncvintr + controller stg0 at isa? port 0x320 bio irq 5 vector stgintr + + #options DPT_MEASURE_PERFORMANCE # Required by DPT driver?? + #options DPT_VERIFY_HINTR # Some hardware must have it! + #options DPT_TRACK_CCB_STATES # Some hardware must have it! + #options DPT_HANDLE_TIMEOUTS # Some hardware must have it! + #options DPT_TIMEOUT_FACTOR=4 # Some hardware needs more + + controller scbus0 + + device sd0 + + device od0 #See LINT for possible `od' options. + + device st0 + + device cd0 #Only need one of these, the code dynamically grows + + #device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr + #device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr + + #controller matcd0 at isa? port 0x230 bio + + #device scd0 at isa? port 0x230 bio + + # syscons is the default console driver, resembling an SCO console + device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr + # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver + #device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint + #options XSERVER # support for X server + #options FAT_CURSOR # start with block cursor + # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines + #options PCVT_SCANSET=2 # IBM keyboards are non-std + + # Mandatory, don't remove + device npx0 at isa? port "IO_NPX" flags 0x1 irq 13 vector npxintr + + # + # Laptop support (see LINT for more options) + # + device apm0 at isa? # Advanced Power Management + options APM_BROKEN_STATCLOCK # Workaround some buggy APM BIOS + + device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr + device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr + device sio2 at isa? disable port "IO_COM3" tty irq 5 vector siointr + device sio3 at isa? disable port "IO_COM4" tty irq 9 vector siointr + device sio4 at isa? disable port "IO_COM3" tty irq 5 vector siointr + + device lpt0 at isa? port? tty irq 7 vector lptintr + device lpt1 at isa? port? tty + #device mse0 at isa? port 0x23c tty irq 5 vector mseintr + + device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr + + # Order is important here due to intrusive probes, do *not* alphabetize + # this list of network interfaces until the probes have been fixed. + # Right now it appears that the ie0 must be probed before ep0. See + # revision 1.20 of this file. + #device de0 + #device fxp0 + #device tl0 + #device tx0 + #device vx0 + #device xl0 + + device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr + device ed1 at isa? disable port 0x300 net irq 10 iomem 0xd8000 vector edintr + #device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector ieintr + device ep0 at isa? port 0x300 net irq 10 vector epintr + device ep1 at isa? disable port 0x300 net irq 10 vector epintr + #device ex0 at isa? port? net irq? vector exintr + device fe0 at isa? port 0x300 net irq 10 vector feintr + device fe1 at isa? disable port 0x300 net irq 10 vector feintr + #device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr + #device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr + device sn0 at isa? port 0x300 net irq 10 vector snintr + device sn1 at isa? disable port 0x300 net irq 10 vector snintr + device wlp0 at isa? port 0x300 net irq 11 vector wlpintr + device wlp1 at isa? disable port 0x300 net irq 11 vector wlpintr + #device cs0 at isa? disable port 0x300 net irq ? vector csintr + device cnw0 at isa? port 0x300 net irq 5 vector cnwintr + device cnw1 at isa? disable port 0x300 net irq 5 vector cnwintr + + # do not enable ze0 and zp0 (these devices are obsolete) + ##device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr + ##device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr + + # IBM Smart Capture PCMCIA card + device scc0 + device scc1 + + # Hitachi microcomputer system Speach Synthesizer card + device hss0 + device hss1 + + # PCMCIA Joystick + device joy0 at isa? port "IO_GAME" + + pseudo-device loop + pseudo-device ether + pseudo-device log + pseudo-device sl 1 + # DHCP uses BPF (Berkeley Packet Filter) + pseudo-device bpfilter 4 + # ijppp uses tun instead of ppp device + #pseudo-device ppp 1 + pseudo-device vn 1 + pseudo-device tun 1 + pseudo-device pty 16 + pseudo-device gzip # Exec gzipped a.out's + + options DDB + + # KTRACE enables the system-call tracing facility ktrace(2). + # This adds 4 KB bloat to your kernel, and slightly increases + # the costs of each syscall. + #options KTRACE #kernel tracing + + # This provides support for System V shared memory. + # + options SYSVSHM + options SYSVSEM + options SYSVMSG + Index: PAO/sys/i386/conf/PCCARD diff -c PAO/sys/i386/conf/PCCARD:1.1.1.1 PAO/sys/i386/conf/PCCARD:1.1.1.1.8.1 *** PAO/sys/i386/conf/PCCARD:1.1.1.1 Sun Apr 5 07:09:39 1998 --- PAO/sys/i386/conf/PCCARD Sun Dec 6 07:46:27 1998 *************** *** 11,17 **** # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # ! # $Id: PCCARD,v 1.1.2.1 1997/11/01 18:55:45 nate Exp $ machine "i386" cpu "I386_CPU" --- 11,17 ---- # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # ! # $Id: PCCARD,v 1.1.1.1.6.1 1998/07/27 09:44:05 kim Exp $ machine "i386" cpu "I386_CPU" *************** *** 53,60 **** --- 53,68 ---- options ATAPI #Enable ATAPI support for IDE bus options ATAPI_STATIC #Don't do it as an LKM device wcd0 #IDE CD-ROM + device wfd0 #IDE floppy (LS-120) controller aic0 at isa? port 0x340 bio irq 11 vector aicintr + controller spc0 at isa? port 0x320 bio irq 11 iomem 0xd0000 flags 0x01 vector spcintr + + # Future domain and Q-logic PC-card SCSI drivers + # ported from NetBSD/pc98 (based on NetBSD 1.2) + options SCSI_LOW # XXX: for ncv? and stg? driver + controller ncv0 at isa? port 0x320 bio irq 5 vector ncvintr + controller stg0 at isa? port 0x320 bio irq 5 vector stgintr controller scbus0 *************** *** 79,87 **** options APM_BROKEN_STATCLOCK # Workaround some buggy APM BIOS # PCCARD (PCMCIA) support ! controller card0 ! device pcic0 at card? ! device pcic1 at card? device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr --- 87,104 ---- options APM_BROKEN_STATCLOCK # Workaround some buggy APM BIOS # PCCARD (PCMCIA) support ! # Dont remove these two lines! ! pseudo-device card 1 ! ! # You must use "flags 0x1" when you don't hear any negotiation noise(?) ! # if you use modem card, or pccardd doesn't read cis tuple, tell you ! # 'No card in database for"(null)"("(null)")' in case of Cirrus Logic's ! # pcic is your PC. ! #device pcic0 at isa? port 0x3e0 flags 0x1 irq 11 vector pcicintr ! device pcic0 at isa? port 0x3e0 irq 11 vector pcicintr ! device pcic0 at isa? port 0x3e4 irq 11 vector pcicintr ! device pcic1 at isa? port 0x3e2 # for HiNote Ultra II ! device pcic1 at isa? port 0x3e4 # for Chandra II device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr *************** *** 95,100 **** --- 112,120 ---- device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device ep0 at isa? port 0x300 net irq 10 vector epintr device fe0 at isa? port 0x300 net irq ? vector feintr + device sn0 at isa? port 0x300 net irq 10 vector snintr + #device wlp0 at isa? port 0x300 net irq 11 vector wlpintr + device cnw0 at isa? port 0x300 net irq 5 vector cnwintr pseudo-device loop pseudo-device ether Index: PAO/sys/i386/conf/files.i386 diff -c PAO/sys/i386/conf/files.i386:1.1.1.4 PAO/sys/i386/conf/files.i386:1.1.1.4.2.2 *** PAO/sys/i386/conf/files.i386:1.1.1.4 Sat Dec 5 05:35:56 1998 --- PAO/sys/i386/conf/files.i386 Wed Dec 23 15:20:44 1998 *************** *** 103,109 **** --- 103,111 ---- i386/isa/gpib.c optional gp device-driver i386/isa/asc.c optional asc device-driver i386/isa/gsc.c optional gsc device-driver + i386/isa/hss.c optional hss device-driver i386/isa/if_ar.c optional ar device-driver + i386/isa/if_cnw.c optional cnw device-driver i386/isa/if_cs.c optional cs device-driver i386/isa/if_cx.c optional cx device-driver i386/isa/if_ed.c optional ed device-driver *************** *** 115,122 **** --- 117,126 ---- i386/isa/if_ie.c optional ie device-driver i386/isa/if_le.c optional le device-driver i386/isa/if_lnc.c optional lnc device-driver + i386/isa/if_sn.c optional sn device-driver i386/isa/if_sr.c optional sr device-driver i386/isa/if_wl.c optional wl device-driver + i386/isa/if_wlp.c optional wlp device-driver i386/isa/if_ze.c optional ze device-driver i386/isa/if_zp.c optional zp device-driver i386/isa/isa.c optional isa device-driver *************** *** 130,135 **** --- 134,140 ---- i386/isa/mcd.c optional mcd device-driver i386/isa/mse.c optional mse device-driver i386/isa/ncr5380.c optional nca device-driver + i386/isa/nin.c optional nin device-driver i386/isa/npx.c optional npx device-driver i386/isa/pcaudio.c optional pca device-driver i386/isa/matcd/matcd.c optional matcd device-driver *************** *** 149,154 **** --- 154,161 ---- i386/isa/qcamio.c optional qcam device-driver i386/isa/random_machdep.c standard i386/isa/rc.c optional rc device-driver + i386/isa/scc.c optional scc device-driver + i386/isa/scc_subr.c optional scc device-driver i386/isa/scd.c optional scd device-driver i386/isa/seagate.c optional sea device-driver i386/isa/si.c optional si device-driver *************** *** 206,211 **** --- 213,219 ---- i386/isa/sound/trix.c optional trix device-driver i386/isa/sound/sscape.c optional sscape device-driver i386/isa/sound/awe_wave.c optional awe device-driver + i386/isa/spc.c optional spc device-driver i386/isa/spigot.c optional spigot device-driver i386/isa/spkr.c optional speaker device-driver i386/isa/stallion.c optional stl device-driver *************** *** 237,242 **** --- 245,256 ---- i386/scsi/aic7xxx.c optional ahc device-driver \ dependency "aic7xxx_{reg,seq}.h" i386/scsi/bt.c optional bt device-driver + i386/scsi/ncr53c500/ncr53c500.c optional ncv device-driver + i386/scsi/ncr53c500/ncr53c500if.c optional ncv device-driver + i386/scsi/tmc18c30/tmc18c30.c optional stg device-driver + i386/scsi/tmc18c30/tmc18c30if.c optional stg device-driver + i386/scsi/scsi_low/scsi_low.c optional scsi_low + i386/scsi/scsi_low/scsi_low_pisa.c optional scsi_low libkern/bcd.c standard libkern/divdi3.c standard libkern/inet_ntoa.c standard Index: PAO/sys/i386/conf/majors.i386 diff -c PAO/sys/i386/conf/majors.i386:1.1.1.4 PAO/sys/i386/conf/majors.i386:1.1.1.4.2.1 *** PAO/sys/i386/conf/majors.i386:1.1.1.4 Sat Dec 5 05:35:57 1998 --- PAO/sys/i386/conf/majors.i386 Sun Dec 6 07:46:29 1998 *************** *** 124,129 **** --- 124,130 ---- 80 xdcp Assigned to Chris Ficklin 81 ?? RocketPort/Steve Gericke 82 ppi Generic Parallel I/O + 83 hss Hitachi microcomputer system Speech Synthesizer card (itojun@itojun.org) 87 wfd ATAPI floppy client of "ata" 88 dpt DPT RAID Controller 89 pps Pulse-Per-Second timing interface Index: PAO/sys/i386/conf/options.i386 diff -c PAO/sys/i386/conf/options.i386:1.1.1.3 PAO/sys/i386/conf/options.i386:1.1.1.3.2.1 *** PAO/sys/i386/conf/options.i386:1.1.1.3 Sat Dec 5 05:35:59 1998 --- PAO/sys/i386/conf/options.i386 Sun Dec 6 07:46:33 1998 *************** *** 83,88 **** --- 83,89 ---- FDC_DEBUG opt_fdc.h FDC_PRINT_BOGUS_CHIPTYPE opt_fdc.h + FDC_YE opt_fdc.h # pcvt(4) has a bunch of options FAT_CURSOR opt_pcvt.h Index: PAO/sys/i386/i386/autoconf.c diff -c PAO/sys/i386/i386/autoconf.c:1.1.1.3 PAO/sys/i386/i386/autoconf.c:1.1.1.3.4.1 *** PAO/sys/i386/i386/autoconf.c:1.1.1.3 Fri Jul 24 19:15:59 1998 --- PAO/sys/i386/i386/autoconf.c Sun Dec 6 07:46:38 1998 *************** *** 225,230 **** --- 225,235 ---- enable_intr(); INTREN(IRQ_SLAVE); + #if NCARD > 0 + /* Initialize PC-card support before ISA drivers are initialized */ + pccard_driver_init(); + #endif + #if NEISA > 0 eisa_configure(); #endif Index: PAO/sys/i386/i386/locore.s diff -c PAO/sys/i386/i386/locore.s:1.1.1.2 PAO/sys/i386/i386/locore.s:1.1.1.2.8.1 *** PAO/sys/i386/i386/locore.s:1.1.1.2 Sun Apr 5 07:09:52 1998 --- PAO/sys/i386/i386/locore.s Sun Dec 6 07:46:39 1998 *************** *** 301,307 **** --- 301,309 ---- * XXX it's not clear that APM can live in the current environonment. * Only pc-relative addressing works. */ + #ifndef NECMG call _apm_setup + #endif #endif call create_pagetables Index: PAO/sys/i386/i386/machdep.c diff -c PAO/sys/i386/i386/machdep.c:1.1.1.3 PAO/sys/i386/i386/machdep.c:1.1.1.3.4.1 *** PAO/sys/i386/i386/machdep.c:1.1.1.3 Fri Jul 24 19:16:07 1998 --- PAO/sys/i386/i386/machdep.c Sun Dec 6 07:46:40 1998 *************** *** 1073,1080 **** --- 1073,1086 ---- /* Use BIOS values stored in RTC CMOS RAM, since probing * breaks certain 386 AT relics. */ + #ifdef NECMG + /* XXX */ + biosbasemem = bootinfo.bi_basemem; + biosextmem = bootinfo.bi_extmem; + #else /* NECMG */ biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); + #endif /* !NECMG */ /* * If BIOS tells us that it has more than 640k in the basemem, Index: PAO/sys/i386/i386/userconfig.c diff -c PAO/sys/i386/i386/userconfig.c:1.1.1.4 PAO/sys/i386/i386/userconfig.c:1.1.1.4.2.1 *** PAO/sys/i386/i386/userconfig.c:1.1.1.4 Sat Dec 5 05:36:16 1998 --- PAO/sys/i386/i386/userconfig.c Sun Dec 6 07:46:42 1998 *************** *** 234,239 **** --- 234,242 ---- {"aic", "Adaptec 152x SCSI and compatible sound cards", 0, CLS_STORAGE}, {"nca", "ProAudio Spectrum SCSI and compatibles", 0, CLS_STORAGE}, {"sea", "Seagate ST01/ST02 SCSI and compatibles", 0, CLS_STORAGE}, + {"spc", "Fujitsu MB89352A (SPC) SCSI controller", 0, CLS_STORAGE}, + {"ncv", "NCR/Symbios 53C500/53C406 SCSI controller", 0, CLS_STORAGE}, + {"stg", "Future Domain TMC18C30/18C50 SCSI controller", 0, CLS_STORAGE}, {"wds", "Western Digitial WD7000 SCSI controller", 0, CLS_STORAGE}, {"ncr", "NCR/Symbios 53C810/15/25/60/75 SCSI controller",FLG_FIXED,CLS_STORAGE}, {"wdc", "IDE/ESDI/MFM disk controller", 0, CLS_STORAGE}, *************** *** 260,265 **** --- 263,270 ---- {"tx", "SMC 9432TX Ethernet adapter", 0, CLS_NETWORK}, {"vx", "3COM 3C590/3C595 Ethernet adapters", 0, CLS_NETWORK}, {"xl", "3COM 3C90x/3C90xB/3C980 Ethernet adapters", 0, CLS_NETWORK}, + {"sn", "SMC/Megahertz Ethernet adapters", 0, CLS_NETWORK}, + {"wlp", "AT&T GIS WaveLAN", 0, CLS_NETWORK}, {"ze", "IBM/National Semiconductor PCMCIA Ethernet adapter",0, CLS_NETWORK}, {"zp", "3COM PCMCIA Etherlink III Ethernet adapter", 0, CLS_NETWORK}, {"de", "DEC DC21040 Ethernet adapter", FLG_FIXED, CLS_NETWORK}, *************** *** 311,316 **** --- 316,322 ---- {"vga", "Catchall PCI VGA driver", FLG_INVISIBLE, CLS_MISC}, {"chip", "PCI chipset support", FLG_INVISIBLE, CLS_MISC}, {"piix", "Intel 82371 Bus-master IDE controller", FLG_INVISIBLE, CLS_MISC}, + {"pcic", "PC Card controller", 0, CLS_MISC}, {"","",0,0}}; Index: PAO/sys/i386/include/apm_bios.h diff -c PAO/sys/i386/include/apm_bios.h:1.1.1.2 PAO/sys/i386/include/apm_bios.h:1.1.1.2.6.3 *** PAO/sys/i386/include/apm_bios.h:1.1.1.2 Sun Apr 5 07:10:32 1998 --- PAO/sys/i386/include/apm_bios.h Tue Dec 22 17:27:56 1998 *************** *** 62,67 **** --- 62,68 ---- #define APM_RESTOREDEFAULT 0x09 #ifdef PC98 #define APM_GETPWSTATUS 0x3a + #define APM_GETPWSTATUS_PC98 0x0a #else #define APM_GETPWSTATUS 0x0a #endif *************** *** 74,79 **** --- 75,84 ---- #define APM_DRVVERSION 0x0e #endif #define APM_ENGAGEDISENGAGEPM 0x0f + #define APM_GETCAPABILITY 0x10 + #define APM_CTLRESUMETIMER 0x11 + #define APM_ENABLEDISABLEROR 0x12 + #define APM_ENABLEDISABLETBR 0x13 #define APM_OEMFUNC 0x80 /* error code */ *************** *** 88,93 **** --- 93,100 ---- #define APME_UNKNOWNDEVICEID 0x09 #define APME_OUTOFRANGE 0x0a #define APME_NOTENGAGED 0x0b + #define APME_UNSUPPORTFUNC 0x0c + #define APME_RESMTIMERDISABLED 0x0d #define APME_CANTENTERSTATE 0x60 #define APME_NOPMEVENT 0x80 #define APME_NOAPMPRESENT 0x86 *************** *** 120,126 **** #define PMDV_PCMCIA1 0x0601 #define PMDV_PCMCIA2 0x0602 #define PMDV_PCMCIA3 0x0603 ! /* 0x0700 - 0xdfff Reserved */ /* 0xe000 - 0xefff OEM-defined power device IDs */ /* 0xf000 - 0xffff Reserved */ --- 127,136 ---- #define PMDV_PCMCIA1 0x0601 #define PMDV_PCMCIA2 0x0602 #define PMDV_PCMCIA3 0x0603 ! /* 0x0700 - 0x7fff Reserved */ ! #define PMDV_BATT0 0x8000 ! #define PMDV_BATT1 0x8001 ! /* 0x8100 - 0xdfff Reserved */ /* 0xe000 - 0xefff OEM-defined power device IDs */ /* 0xf000 - 0xffff Reserved */ *************** *** 152,161 **** --- 162,173 ---- #define NAPM_HOOK 2 void apm_suspend(void); + void apm_standby(void); struct apmhook *apm_hook_establish (int apmh, struct apmhook *); void apm_hook_disestablish (int apmh, struct apmhook *); void apm_cpu_idle(void); void apm_cpu_busy(void); + void apm_power_off(int, void*); #endif /* !ASSEMBLER && !INITIALIZER */ *************** *** 178,184 **** #define PMEV_USERSTANDBYREQ 0x0009 #define PMEV_USERSUSPENDREQ 0x000a #define PMEV_STANDBYRESUME 0x000b ! /* 0x000c - 0x00ff Reserved system events */ /* 0x0100 - 0x01ff Reserved device events */ /* 0x0200 - 0x02ff OEM-defined APM events */ /* 0x0300 - 0xffff Reserved */ --- 190,197 ---- #define PMEV_USERSTANDBYREQ 0x0009 #define PMEV_USERSUSPENDREQ 0x000a #define PMEV_STANDBYRESUME 0x000b ! #define PMEV_CAPABLITYCHANGE 0x000c ! /* 0x000d - 0x00ff Reserved system events */ /* 0x0100 - 0x01ff Reserved device events */ /* 0x0200 - 0x02ff OEM-defined APM events */ /* 0x0300 - 0xffff Reserved */ *************** *** 194,199 **** --- 207,221 ---- u_int ai_batt_life; /* Remaining battery life */ u_int ai_status; /* Status of APM support (enabled/disabled) */ } *apm_info_t; + + struct apm_bios_arg { + u_long eax; + u_long ebx; + u_long ecx; + u_long edx; + u_long esi; + u_long edi; + }; #define APMIO_SUSPEND _IO('P', 1) #define APMIO_GETINFO _IOR('P', 2, struct apm_info) Index: PAO/sys/i386/include/clock.h diff -c PAO/sys/i386/include/clock.h:1.1.1.1 PAO/sys/i386/include/clock.h:1.1.1.1.8.1 *** PAO/sys/i386/include/clock.h:1.1.1.1 Thu Dec 11 22:36:51 1997 --- PAO/sys/i386/include/clock.h Sun Dec 6 07:46:46 1998 *************** *** 59,64 **** --- 59,65 ---- int release_timer1 __P((void)); #endif int sysbeep __P((int pitch, int period)); + int sysbeep_cancel __P((void)); #ifdef CLOCK_HAIR Index: PAO/sys/i386/include/console.h diff -c PAO/sys/i386/include/console.h:1.1.1.2 PAO/sys/i386/include/console.h:1.1.1.2.8.1 *** PAO/sys/i386/include/console.h:1.1.1.2 Sun Apr 5 07:10:37 1998 --- PAO/sys/i386/include/console.h Sun Dec 6 07:46:47 1998 *************** *** 152,157 **** --- 152,158 ---- #define KD_EGA 4 /* enhanced graphics adapter */ #define KD_VGA 5 /* video graphics adapter */ #define KD_PC98 6 /* PC-98 display */ + #define KD_NECMG 7 /* Mobile Gear display */ #define KD_TEXT 0 /* set text mode restore fonts */ #define KD_TEXT0 0 /* ditto */ Index: PAO/sys/i386/include/cpu.h diff -c PAO/sys/i386/include/cpu.h:1.1.1.1 PAO/sys/i386/include/cpu.h:1.1.1.1.8.1 *** PAO/sys/i386/include/cpu.h:1.1.1.1 Thu Dec 11 22:36:51 1997 --- PAO/sys/i386/include/cpu.h Sun Dec 6 07:46:48 1998 *************** *** 129,135 **** #define CPU_DISRTCSET 3 /* int: disable resettodr() call */ #define CPU_BOOTINFO 4 /* struct: bootinfo */ #define CPU_WALLCLOCK 5 /* int: indicates wall CMOS clock */ ! #define CPU_MAXID 6 /* number of valid machdep ids */ #define CTL_MACHDEP_NAMES { \ { 0, 0 }, \ --- 129,138 ---- #define CPU_DISRTCSET 3 /* int: disable resettodr() call */ #define CPU_BOOTINFO 4 /* struct: bootinfo */ #define CPU_WALLCLOCK 5 /* int: indicates wall CMOS clock */ ! #define CPU_INTRINUSE 6 /* int: intrs in use */ ! #define CPU_CHECKIO 7 /* int: can we allocate the ioaddr? */ ! #define CPU_CHECKMEM 8 /* int: can we allocate the memory? */ ! #define CPU_MAXID 9 /* number of valid machdep ids */ #define CTL_MACHDEP_NAMES { \ { 0, 0 }, \ *************** *** 138,143 **** --- 141,149 ---- { "disable_rtc_set", CTLTYPE_INT }, \ { "bootinfo", CTLTYPE_STRUCT }, \ { "wall_cmos_clock", CTLTYPE_INT }, \ + { "intr_inuse", CTLTYPE_INT }, \ + { "checkio", CTLTYPE_INT }, \ + { "checkmem", CTLTYPE_INT }, \ } #ifdef KERNEL Index: PAO/sys/i386/include/if_cnwioctl.h diff -c /dev/null PAO/sys/i386/include/if_cnwioctl.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:39 1998 --- PAO/sys/i386/include/if_cnwioctl.h Sun Dec 6 07:46:49 1998 *************** *** 0 **** --- 1,89 ---- + /* + * Copyright (c) 1996 Berkeley Software Design, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that this notice is retained, + * the conditions in the following notices are met, and terms applying + * to contributors in the following notices also apply to Berkeley + * Software Design, Inc. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by + * Berkeley Software Design, Inc. + * 4. Neither the name of the Berkeley Software Design, Inc. nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * BSDI $Id: if_cnwioctl.h,v 1.1.8.1 1998/12/05 22:46:49 itojun Exp $ + */ + struct cnwstatus { + struct ifreq ifr; + u_char data[0x100]; + }; + + struct cnwstats { + u_int nws_rx; + u_int nws_rxerr; + u_int nws_rxoverflow; + u_int nws_rxoverrun; + u_int nws_rxcrcerror; + u_int nws_rxframe; + u_int nws_rxerrors; + u_int nws_rxavail; + u_int nws_rxone; + u_int nws_tx; + u_int nws_txokay; + u_int nws_txabort; + u_int nws_txlostcd; + u_int nws_txerrors; + u_int nws_txretries[16]; + }; + + struct cnwistats { + struct ifreq ifr; + struct cnwstats stats; + }; + + struct cnwtrail { + u_char what; + u_char status; + u_short length; + struct timeval when; + struct timeval done; + }; + + struct cnwitrail { + struct ifreq ifr; + int head; + struct cnwtrail trail[128]; + }; + + #define ifr_domain ifr_ifru.ifru_flags /* domain */ + #define ifr_key ifr_ifru.ifru_flags /* scramble key */ + + #define SIOCSCNWDOMAIN _IOW('i', 254, struct ifreq) /* set domain */ + #define SIOCGCNWDOMAIN _IOWR('i', 253, struct ifreq) /* get domain */ + #define SIOCSCNWKEY _IOWR('i', 252, struct ifreq) /* set scramble key */ + #define SIOCGCNWSTATUS _IOWR('i', 251, struct cnwstatus)/* get raw status */ + #define SIOCGCNWSTATS _IOWR('i', 250, struct cnwistats)/* get stats */ + #define SIOCGCNWTRAIL _IOWR('i', 249, struct cnwitrail)/* get trail */ Index: PAO/sys/i386/include/scc.h diff -c /dev/null PAO/sys/i386/include/scc.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:40 1998 --- PAO/sys/i386/include/scc.h Sun Dec 6 07:46:50 1998 *************** *** 0 **** --- 1,117 ---- + /* + * IBM Smart Capture Card driver. + * + * Copyright (c) 1996 + * Koji OKAMURA and Takeshi OHASHI. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Koji OKAMURA + * and Takeshi OHASHI. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KOJI OKAMURA, TAKESHI OHASHI AND + * CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Changed by Koji OKAMURA + * Changed by Takeshi OHASHI + * Version 0.33, Aug 8, 1996. + * + */ + + typedef struct scc_geomet { + int width; + int height; + } scc_geomet_t ; + + typedef struct scc_color { + int brightness; + int contrast; + int saturation; + int hue; + } scc_color_t ; + + typedef struct scc_tv { + int tuntype; + int channel; + int fine; + int country; + } scc_tv_t ; + + typedef struct scc_card { + int mode; + scc_geomet_t geomet; + int format; + int spdmode; + scc_tv_t tv; + scc_color_t color; + int intput; + } scc_card_t; + + #define SCCSETMODE _IOW('s', 1, int) + #define SCCGETMODE _IOR('s', 2, int) + #define SCCSETGEO _IOW('s', 3, scc_geomet_t) + #define SCCGETGEO _IOR('s', 4, scc_geomet_t) + #define SCCSETFMT _IOW('s', 5, int) + #define SCCGETFMT _IOR('s', 6, int) + #define SCCSETSPDMODE _IOW('s', 7, int) + #define SCCGETSPDMODE _IOR('s', 8, int) + #define SCCSETTVCHANNEL _IOW('s', 9, scc_tv_t) + #define SCCGETTVCHANNEL _IOR('s',10, scc_tv_t) + #define SCCSETCOLOR _IOW('s',11, scc_color_t) + #define SCCGETCOLOR _IOR('s',12, scc_color_t) + + #define SCC_PAL 0 + #define SCC_NTSC 1 + + #define SCC_NTSCWIDTH 640 + #define SCC_NTSCHEIGHT 240 + #define SCC_PALWIDTH 768 + #define SCC_PALHEIGHT 288 + + #define SCC_YUV422 0 + #define SCC_YUV444 1 + #define SCC_YUV411 2 + #define SCC_YUVDPCM 3 + #define SCC_RGB888N 4 + #define SCC_RGB888 5 + #define SCC_RGB565 6 + #define SCC_RGB555 7 + + #define SCC_SLOW 1 + #define SCC_FAST 0 + + #define SCC_DEFBRIGHTNESS 150 + #define SCC_DEFCONTRAST 40 + #define SCC_DEFSATURATION 2800 + #define SCC_DEFHUE 2048 + + #define SCC_MAXBRIGHTNESS 255 + #define SCC_MAXCONTRAST 63 + #define SCC_MAXSATURATION 4095 + #define SCC_MAXHUE 4095 + + #define SCC_MINCHANNELJP 1 + #define SCC_MAXCHANNELJP 62 + #define SCC_MINCHANNELUS 2 + #define SCC_MAXCHANNELUS 69 Index: PAO/sys/i386/include/wavelan.h diff -c /dev/null PAO/sys/i386/include/wavelan.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:40 1998 --- PAO/sys/i386/include/wavelan.h Sun Dec 6 07:46:51 1998 *************** *** 0 **** --- 1,243 ---- + /* + * HISTORY + * $Log: wavelan.h,v $ + * Revision 1.1.8.1 1998/12/05 22:46:51 itojun + * sync with pao227 branch. + * right now, pao228 = r228 + (pao227 - r227) + (bsd-nomads 9735) + * + * confirmed that PAO_ALL is compileable **on 227 system**. need your checks. + * + * Revision 1.1.6.1 1998/08/04 03:04:56 kim + * pao227 release added files + * PR: + * Reviewed by: + * Submitted by: + * Obtained from: + * + * Revision 1.1.4.1 1998/04/04 23:23:41 itojun + * PAO for FreeBSD 2.2.6-RELEASE. + * I dunno if it compiles or not... + * + * Submitted by: thasegawa@mta.biglobe.ne.jp + * + * Revision 1.1.2.1 1997/12/11 13:59:42 itojun + * PAO-971210 import. hope this works well... + * + * Obtained from: hosokawa + * + * Revision 1.1 1994/06/02 20:31:11 klemets + * Initial revision + * + */ + #ifndef _CHIPS_WAVELAN_H + #define _CHIPS_WAVELAN_H + + /* This file contains definitions that are common for all versions of + * the NCR WaveLAN + */ + + #define WAVELAN_ADDR_SIZE 6 /* Size of a MAC address */ + #define WAVELAN_MTU 1500 /* Maximum size of Wavelan packet */ + + struct wl_cntrs { + struct { + u_int xmt, xmti; + u_int defer; + u_int busy; + u_int sleaze, intrinsic, intrinsic_count; + u_int chain; + u_int heart; + u_int coll; + u_int ncoll; + u_int nodcd; + u_int nocts; + u_int dma; + } xmt; + struct { + u_int rcv; + u_int ovw; + u_int crc; + u_int frame; + u_int rscerrs, ovrnerrs; + u_int partial; + u_int snr[5]; + } rcv; + struct { + u_short status; + u_short nwids; + u_short badnwids; + u_short thrpreset; + u_short siglvl; + u_short sillvl; + u_short sigqual; + u_short netwidl; + u_short des; + } mmc; + u_int watch; + }; + typedef struct wl_cntrs *wl_cntrs_t; + + #define CNTR_NAME "_wl_cntrs" + + /* command unit for wlsetstat */ + struct wl_ucmd { + int cmd; + int param; + }; + typedef struct wl_ucmd *wl_ucmd_t; + + #ifdef IF_CNTRS + /* interface driver specific counters */ + struct wl_ifcntrs { + int pkt_arp; + int pkt_ein[32]; + int pkt_lin[128/8]; + int pkt_eout[32]; + int pkt_lout[128/8]; + }; + typedef struct wl_ifcntrs *wl_ifcntrs_t; + #define NET_WL_IFCNTRS (('w'<<16) + 3) + #define NET_WL_IFCNTRS_CNT (sizeof (struct wl_ifcntrs)/sizeof(int)) + #endif IF_CNTRS + + /* local flavor value for wlsetstat and wlgetstat */ + #define NET_WL_CNTRS (('w'<<16) + 1) + #define NET_WL_CMD (('w'<<16) + 2) + #define NET_WL_PSA (('w'<<24) + ('l'<<16)) + #define NET_WL_CNTRS_CNT (sizeof (struct wl_cntrs)/sizeof(int)) + #define NET_WL_CMD_CNT (sizeof (struct wl_ucmd)/sizeof(int)) + #define NET_WL_PSA_CNT 1 + + #ifdef IF_LINKSTATUS + #define NET_LINKSTATE (('w'<<16) + 4) + #define NET_LADDR_ADD (('w'<<16) + 5) + #define NET_LADDR_DEL (('w'<<16) + 6) + #define NET_LADDR_ADD_CNT ((WAVELAN_ADDR_SIZE + sizeof(int) - 1)/sizeof(int)) + #define NET_LADDR_DEL_CNT ((WAVELAN_ADDR_SIZE + sizeof(int) - 1)/sizeof(int)) + #define MAX_LINKADDR 64 + #endif IF_LINKSTATUS + + + /* local commands */ + #define WLCMD_CLEAR 1 + #define WLCMD_SENDCMD 2 + #define WLCMD_SETNWID 3 + #define WLCMD_SETIRQ 4 + #define WLCMD_PARAM 5 + #define WLCMD_POWER_DOWN 6 + #define WLCMD_POWER_UP 7 + + #define DEFAULT_PSA_OFFSET 0xe00 + + /* Allocations in general purpose software block */ + + #define NETW_ADDR 0x10 /* Factory network address */ + #define NETW_ADDR_LOCAL 0x16 /* Local network address */ + #define PSA_MAC_SELECT 0x1c /* 0=factory, 1=local address */ + #define PSA_COMP_NUMBER 0x1d /* 0=PC-AT 915 MHz, 1=PC-MC 915 MHz + 2=PC-AT 2.4 GHz, 3=PC-MC 2.4 GHz + 4=PCMCIA 915 MHz */ + #define PSA_THR_PRE_SET 0x1e + #define PSA_FEATURE_SELECT 0x1f + #define PSA_SUBBAND 0x20 /* 1=2425 MHz, 2=2460 MHz, 3=2484 MHz + 4=2430.5 MHz */ + #define PSA_QUALITY_THR 0x21 + #define NETW_ID 0x23 /* Network ID */ + #define PSA_NETW_ID_SELECT 0x25 + #define PSA_SECURITY_SELECT 0x26 + #define PSA_ENCRYPTION_KEY 0x27 + #define PSA_DATABUS_WIDTH 0x2f + #define PSA_CALL_CODE 0x30 + #define PSA_NWID_PREFIX 0x38 + #define PSA_CONF_STATUS 0x3c + #define PSA_CRC 0x3d + #define PSA_CRC_STATUS 0x3f + + /* Modem Management Controler write commands */ + + #define MMC_LOOPT_SEL 0x10 + #define MMC_JABBER_ENABLE 0x11 + #define MMC_FREEZE 0x12 + #define MMC_ANTEN_SEL 0x13 + #define MMC_IFS 0x14 + #define MMC_MOD_DELAY 0x15 + #define MMC_JAM_TIME 0x16 + #define MMC_THR_PRE_SET 0x18 + #define MMC_DECAY_PRM 0x19 + #define MMC_DECAY_UPDAT_PRM 0x1a + #define MMC_QUALITY_THR 0x1b + #define MMC_NETW_ID_L 0x1c + #define MMC_NETW_ID_H 0x1d + #define MMC_MODE_SEL 0x1e + #define MMC_ENCR_KEY 0x00 /* to 0x07 */ + #define MMC_ENCR_ENABLE 0x08 + #define MMC_DES_IO_INVERT 0x0a + + /* MMC read register names */ + + #define MMC_DCE_STATUS 0x10 + #define MMC_CORRECT_NWID_L 0x14 + #define MMC_CORRECT_NWID_H 0x15 + #define MMC_WRONG_NWID_L 0x16 + #define MMC_WRONG_NWID_H 0x17 + #define MMC_THR_PRE_SET 0x18 + #define MMC_SIGNAL_LVL 0x19 + #define MMC_SILENCE_LVL 0x1a + #define MMC_SIGN_QUAL 0x1b + #define MMC_DES_AVAIL 0x09 + + struct wavelan_conf { + u_char wc_confstat; + u_char wc_nwid[2]; + u_char wc_macaddr[6]; + u_char wc_comp_number; + u_char wc_subband; + u_char wc_netw_id_sel; + u_char wc_thr_pre_set; + u_char wc_quality_thr; + }; + + + /* additional socket ioctl params for wl card + * see sys/sockio.h for numbers. The 2nd params here + * must be greater than any values in sockio.h + */ + + #define SIOCGWLNWID _IOWR('i', 60, struct ifreq) /* get wlan nwid */ + #define SIOCSWLNWID _IOWR('i', 61, struct ifreq) /* set wlan nwid */ + + /* + * signal strength cache + * + * driver (wlp only at the moment) keeps cache of last + * IP (only) packets to arrive including signal strength info. + * daemons may read this with kvm. See if_wlp.c for globals + * that may be accessed through kvm. + * + * Each entry in the w_sigcache has a unique macsrc and age. + * Each entry is identified by its macsrc field. + * Age of the packet is identified by its age field. + */ + + #define MAXCACHEITEMS 10 + #ifndef INT_MAX + #define INT_MAX 2147483647 + #endif + #define MAX_AGE (INT_MAX - MAXCACHEITEMS) + + /* signal is 7 bits, 0..63, although it doesn't seem to get to 63. + * silence is 7 bits, 0..63 + * quality is 4 bits, 0..15 + */ + struct w_sigcache { + char macsrc[6]; /* unique MAC address for entry */ + int ipsrc; /* ip address associated with packet */ + int signal; /* signal strength of the packet */ + int silence; /* silence of the packet */ + int quality; /* quality of the packet */ + int age; /* packet has unique age between 1 to MAX_AGE - 1 */ + }; + + + #endif _CHIPS_WAVELAN_H + Index: PAO/sys/i386/isa/aic6360.c diff -c PAO/sys/i386/isa/aic6360.c:1.1.1.3 PAO/sys/i386/isa/aic6360.c:1.1.1.3.4.1 *** PAO/sys/i386/isa/aic6360.c:1.1.1.3 Fri Jul 24 19:17:14 1998 --- PAO/sys/i386/isa/aic6360.c Sun Dec 6 07:46:54 1998 *************** *** 646,651 **** --- 646,652 ---- #define AIC_START(str) #endif + /*void aicintr __P((int));*/ static int aicprobe __P((struct isa_device *)); static int aicattach __P((struct isa_device *)); static void aic_minphys __P((struct buf *)); *************** *** 657,664 **** static void aic_datain __P((struct aic_data *aic)); static int32_t aic_scsi_cmd __P((struct scsi_xfer *)); static int aic_poll __P((struct aic_data *aic, struct acb *)); ! void aic_add_timeout __P((struct acb *, int)); ! void aic_remove_timeout __P((struct acb *)); static void aic6360_reset __P((struct aic_data *aic)); static u_short aicphase __P((struct aic_data *aic)); static void aic_msgin __P((struct aic_data *aic)); --- 658,665 ---- static void aic_datain __P((struct aic_data *aic)); static int32_t aic_scsi_cmd __P((struct scsi_xfer *)); static int aic_poll __P((struct aic_data *aic, struct acb *)); ! /*void aic_add_timeout __P((struct acb *, int));*/ ! /*void aic_remove_timeout __P((struct acb *));*/ static void aic6360_reset __P((struct aic_data *aic)); static u_short aicphase __P((struct aic_data *aic)); static void aic_msgin __P((struct aic_data *aic)); *************** *** 670,676 **** --- 671,681 ---- void aic_print_active_acb __P((void)); void aic_dump6360 __P((void)); void aic_dump_driver __P((void)); + #endif + #ifdef SCSI_DETACH + static void aicdetach __P((struct isa_device *dev)); + #endif /* SCSI_DETACH */ /* Linkup to the rest of the kernel */ struct isa_driver aicdriver = { *************** *** 731,740 **** static int already_aicinit[NAIC]; /* validate unit number */ ! if (devi->isahd.id_unit >= NAIC) return(ENODEV); /* Make sure it isn't already initialised */ ! if (already_aicinit[devi->isahd.id_unit] == 1) { if (aicattach(&devi->isahd) == 0) return(ENXIO); return(0); --- 736,745 ---- static int already_aicinit[NAIC]; /* validate unit number */ ! if (devi->pd_unit >= NAIC) return(ENODEV); /* Make sure it isn't already initialised */ ! if (already_aicinit[devi->pd_unit] == 1) { if (aicattach(&devi->isahd) == 0) return(ENXIO); return(0); *************** *** 748,754 **** if (aicattach(&devi->isahd) == 0) return(ENXIO); ! already_aicinit[devi->isahd.id_unit] = 1; return(0); } --- 753,759 ---- if (aicattach(&devi->isahd) == 0) return(ENXIO); ! already_aicinit[devi->pd_unit] = 1; return(0); } *************** *** 764,772 **** void aicunload(struct pccard_devinfo *devi) { ! printf("aic%d: unload\n", devi->isahd.id_unit); #if 0 ! aicstop(devi->isahd.id_unit); #endif } --- 769,780 ---- void aicunload(struct pccard_devinfo *devi) { ! printf("aic%d: unload\n", devi->pd_unit); #if 0 ! aicstop(devi->pd_unit); ! #endif ! #ifdef SCSI_DETACH ! aicdetach(&devi->isahd); #endif } *************** *** 776,782 **** static int aic_card_intr(struct pccard_devinfo *devi) { ! aicintr(devi->isahd.id_unit); return(1); } #endif /* NCARD > 0 */ --- 784,790 ---- static int aic_card_intr(struct pccard_devinfo *devi) { ! aicintr(devi->pd_unit); return(1); } #endif /* NCARD > 0 */ *************** *** 899,904 **** --- 907,926 ---- AIC_START(("chip revision %d\n",(int)inb(REV))); return 0; } + + #ifdef SCSI_DETACH + static void + aicdetach(dev) + struct isa_device *dev; + { + int unit = dev->id_unit; + struct aic_data *aic = aicdata[unit]; + struct scsibus_data *scbus; + + scbus = (struct scsibus_data *)scsi_extend_get(aicdata[unit]->sc_link.scsibus); + scsi_detachdev(scbus); + } + #endif /* SCSI_DETACH */ /* * Attach the AIC6360, fill out some high and low level data structures Index: PAO/sys/i386/isa/atapi-cd.c diff -c PAO/sys/i386/isa/atapi-cd.c:1.1.1.1 PAO/sys/i386/isa/atapi-cd.c:1.1.1.1.2.1 *** PAO/sys/i386/isa/atapi-cd.c:1.1.1.1 Sat Dec 5 05:37:16 1998 --- PAO/sys/i386/isa/atapi-cd.c Wed Dec 23 15:05:50 1998 *************** *** 84,95 **** --- 84,105 ---- #define F_WRITTEN 0x0080 /* The medium has been written to */ static struct acd *acdtab[NUNIT]; + #ifndef ATAPI_DETACH static int acdnlun = 0; /* Number of configured drives */ + #else /* ATAPI_DETACH */ + static int acd_unit_use = 0; /* Number of configured drives */ + #endif /* ATAPI_DETACH */ #ifndef ATAPI_STATIC static #endif int acdattach(struct atapi *, int, struct atapi_params *, int); + #ifdef ATAPI_DETACH + #ifndef ATAPI_STATIC + static + #endif + int acddetach(struct atapi *, int, struct atapi_params *, int); + #endif /* ATAPI_DETACH */ static struct acd *acd_init_lun(struct atapi *, int, struct atapi_params *,int); static void acd_start(struct acd *); static void acd_done(struct acd *, struct buf *, int, struct atapires); *************** *** 161,168 **** struct atapires result; struct changer *chp; int i, count; ! if (acdnlun >= NUNIT) { printf("acd: too many units\n"); return 0; } --- 171,187 ---- struct atapires result; struct changer *chp; int i, count; + int lun; ! #ifndef ATAPI_DETACH ! lun = acdnlun; ! #else /* ATAPI_DETACH */ ! for (lun = 0; lun < NUNIT; lun++) { ! if (!(acd_unit_use & (1 << lun))) ! break; ! } ! #endif /* ATAPI_DETACH */ ! if (lun >= NUNIT) { printf("acd: too many units\n"); return 0; } *************** *** 170,180 **** printf("acd: configuration error, ATAPI code not present!\n"); return 0; } ! if ((cdp = acd_init_lun(ata, unit, ap, acdnlun)) == NULL) { printf("acd: out of memory\n"); return 0; } ! acdtab[acdnlun] = cdp; if (debug) { cdp->flags |= F_DEBUG; --- 189,199 ---- printf("acd: configuration error, ATAPI code not present!\n"); return 0; } ! if ((cdp = acd_init_lun(ata, unit, ap, lun)) == NULL) { printf("acd: out of memory\n"); return 0; } ! acdtab[lun] = cdp; if (debug) { cdp->flags |= F_DEBUG; *************** *** 232,237 **** --- 251,257 ---- if (result.code == 0) { chp->table_length = htons(chp->table_length); + #ifndef ATAPI_DETACH for (i = 0; i < chp->slots && acdnlun < NUNIT; i++) { if (i > 0) { cdp = acd_init_lun(ata, unit, ap, acdnlun); *************** *** 250,261 **** --- 270,372 ---- printf("acd: too many units\n"); return 0; } + #else /* ATAPI_DETACH */ + for (i = 0; i < chp->slots; i++) { + if (i > 0) { + while (++lun < NUNIT) { + if (!(acd_unit_use & (1 << lun))) + break; + } + if (lun >= NUNIT) { + printf("acd: too many units\n"); + return 0; + } + cdp = acd_init_lun(ata, unit, ap, lun); + if (cdp == NULL) { + printf("acd: out of memory\n"); + return 0; + } + } + cdp->slot = i; + cdp->changer_info = chp; + printf("acd%d: changer slot %d %s\n", lun, i, + (chp->slot[i].present ? "disk present" : "no disk")); + acdtab[lun] = cdp; + acd_unit_use |= (1 << lun); + } + #endif /* ATAPI_DETACH */ } } else + #ifndef ATAPI_DETACH acdnlun++; + #else /* ATAPI_DETACH */ + acd_unit_use |= (1 << lun); + #endif /* ATAPI_DETACH */ return 1; } + #ifdef ATAPI_DETACH + #ifndef ATAPI_STATIC + static + #endif + int + acddetach(struct atapi *ata, int unit, struct atapi_params *ap, int debug) + { + struct acd *cdp; + struct changer *chp = NULL; + int lun; + int slot[NUNIT]; + int i = 1; + + for (lun = 0; lun < NUNIT; lun++) { + if ((acd_unit_use & (1 << lun))) { + cdp = acdtab[lun]; + if (cdp->ata->port == ata->port && + cdp->ata->ctrlr == ata->ctrlr && + cdp->unit == unit) + break; + } + } + if (lun >= NUNIT) { + printf("acd: not found unit\n"); + return 0; + } + + if ((cdp->flags & F_BOPEN) || cdp->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + + slot[0] = lun; + chp = cdp->changer_info; + if (chp) { + while (++lun < NUNIT) { + if ((acd_unit_use & (1 << lun))) { + cdp = acdtab[lun]; + if (cdp->changer_info == chp) { + slot[i++] = lun; + if ((cdp->flags & F_BOPEN) || cdp->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + } + } + } + free(chp, M_TEMP); + } + + while (i--) { + lun = slot[i]; + cdp = acdtab[lun]; + + cdp->ata->attached[unit] = 0; + free(cdp, M_TEMP); + acdtab[lun] = NULL; + + acd_unit_use &= ~(1 << lun); + } + return 0; + } + #endif /* ATAPI_DETACH */ + void acd_describe(struct acd *cdp) { *************** *** 384,391 **** --- 495,507 ---- int track = dkslice(dev); /* XXX this is a hack... */ struct acd *cdp; + #ifndef ATAPI_DETACH if (lun >= acdnlun || !atapi_request_immediate) return ENXIO; + #else /* ATAPI_DETACH */ + if (!(acd_unit_use & (1 << lun)) || !atapi_request_immediate) + return ENXIO; + #endif /* ATAPI_DETACH */ cdp = acdtab[lun]; if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) { *************** *** 1694,1709 **** int acd_unload(struct lkm_table *lkmtp, int cmd) { struct acd **cdpp; ! for (cdpp = acdtab; cdpp < acdtab + acdnlun; ++cdpp) if (((*cdpp)->flags & F_BOPEN) || (*cdpp)->refcnt) return EBUSY; for (cdpp = acdtab; cdpp < acdtab + acdnlun; ++t) { (*cdpp)->ata->attached[(*cdpp)->unit] = 0; free(*cdpp, M_TEMP); } acdnlun = 0; bzero(acdtab, sizeof(acdtab)); return 0; } --- 1810,1855 ---- int acd_unload(struct lkm_table *lkmtp, int cmd) { + struct changer *chp[NUNIT]; + int nch = 0; + + #ifndef ATAPI_DETACH struct acd **cdpp; ! for (cdpp = acdtab; cdpp < acdtab + acdnlun; ++cdpp) { if (((*cdpp)->flags & F_BOPEN) || (*cdpp)->refcnt) return EBUSY; + if ((*chpp)->changer_info) + chp[nch++] = (*chpp)->changer_info; + } for (cdpp = acdtab; cdpp < acdtab + acdnlun; ++t) { (*cdpp)->ata->attached[(*cdpp)->unit] = 0; free(*cdpp, M_TEMP); } acdnlun = 0; + #else /* ATAPI_DETACH */ + struct acd *cdp; + int lun; + + for (lun = 0; lun < NUNIT; ++lun) + if (acd_unit_use & (1 << lun)) { + cdp = acdtab[lun]; + if ((cdp->flags & F_BOPEN) || cdp->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + if (chp->changer_info) + chp[nch++] = chp->changer_info; + } + for (lun = 0; lun < NUNIT; ++lun) + if (acd_unit_use & (1 << lun)) { + cdp = acdtab[lun]; + cdp->ata->attached[cdp->unit] = 0; + free(cdp, M_TEMP); + } + acd_unit_use = 0; + #endif /* ATAPI_DETACH */ + while (nch--) + free(chp[nch], M_TEMP); bzero(acdtab, sizeof(acdtab)); return 0; } Index: PAO/sys/i386/isa/atapi.c diff -c PAO/sys/i386/isa/atapi.c:1.1.1.4 PAO/sys/i386/isa/atapi.c:1.1.1.4.2.3 *** PAO/sys/i386/isa/atapi.c:1.1.1.4 Sat Dec 5 05:37:16 1998 --- PAO/sys/i386/isa/atapi.c Wed Dec 23 19:27:22 1998 *************** *** 145,150 **** --- 145,156 ---- ++atapi_ndrv; return (1); } + + #ifdef ATAPI_DETACH + int atapi_detach (int ctlr, int unit, int port) + { + } + #endif /* ATAPI_DETACH */ #else /* ATAPI_STATIC */ /* this code is compiled part of the module */ *************** *** 176,181 **** --- 182,192 ---- extern int acdattach(struct atapi*, int, struct atapi_params*, int); extern int wfdattach(struct atapi*, int, struct atapi_params*, int); extern int wcdattach(struct atapi*, int, struct atapi_params*, int); + #ifdef ATAPI_DETACH + extern int acddetach(struct atapi*, int, struct atapi_params*, int); + extern int wcddetach(struct atapi*, int, struct atapi_params*, int); + extern int wfddetach(struct atapi*, int, struct atapi_params*, int); + #endif /* ATAPI_DETACH */ /* * Probe the ATAPI device at IDE controller `ctlr', drive `unit'. *************** *** 292,297 **** --- 303,311 ---- /* ATAPI Floppy(LS-120) */ if (wfdattach (ata, unit, ap, ata->debug) >= 0) { /* Device attached successfully. */ + #ifdef ATAPI_DETACH + ata->params[unit] = ap; + #endif /* ATAPI_DETACH */ ata->attached[unit] = 1; return (1); } *************** *** 301,306 **** --- 315,323 ---- /* ATAPI CD-ROM & CD-R/RW drives */ if (acdattach (ata, unit, ap, ata->debug) < 0) break; + #ifdef ATAPI_DETACH + ata->params[unit] = ap; + #endif /* ATAPI_DETACH */ ata->attached[unit] = 1; return (1); #else *************** *** 308,313 **** --- 325,333 ---- /* ATAPI CD-ROM drives */ if (wcdattach (ata, unit, ap, ata->debug) < 0) break; + #ifdef ATAPI_DETACH + ata->params[unit] = ap; + #endif /* ATAPI_DETACH */ ata->attached[unit] = 1; return (1); #else *************** *** 338,343 **** --- 358,432 ---- #endif /* ATAPI_MODULE */ } + #ifdef ATAPI_DETACH + #ifdef ATAPI_MODULE + static + #endif + int atapi_detach (int ctlr, int unit, int port) + { + struct atapi *ata = atapitab + ctlr; + struct atapi_params *ap = ata->params[unit]; + + if (ata->ctrlr == ctlr && + ata->port == port && ap) { + switch (ap->devtype) { + default: + /* unknown ATAPI device */ + break; + + case AT_TYPE_DIRECT: /* direct-access */ + #if NWFD > 0 + /* ATAPI Floppy(LS-120) */ + if (wfddetach (ata, unit, ap, ata->debug) >= 0) { + /* Device detached successfully. */ + ata->attached[unit] = 0; + goto detach_success; + } + #endif + case AT_TYPE_CDROM: /* CD-ROM device */ + #if NACD > 0 + /* ATAPI CD-ROM & CD-R/RW drives */ + if (acddetach (ata, unit, ap, ata->debug) < 0) + break; + /* Device detached successfully. */ + ata->attached[unit] = 0; + #else + #if NWCD > 0 + /* ATAPI CD-ROM drives */ + if (wcddetach (ata, unit, ap, ata->debug) < 0) + break; + /* Device detached successfully. */ + ata->attached[unit] = 0; + #endif + #endif + break; + + case AT_TYPE_TAPE: /* streaming tape (QIC-121 model) */ + #if NWMT > 0 + /* Add your driver here */ + #endif + break; + + case AT_TYPE_OPTICAL: /* optical disk */ + #if NWMD > 0 + /* Add your driver here */ + #endif + break; + } + /* Detach failed. */ + if (ata->attached[unit]) + return EBUSY; + + detach_success: + if (ata->params[unit]) { + free (ata->params[unit], M_TEMP); + ata->params[unit] = 0; + } + } + return (1); + } + #endif /* ATAPI_DETACH */ + static char *cmdname (u_char cmd) { static char buf[8]; *************** *** 466,475 **** /* * Shuffle string byte order. ! * Mitsumi and NEC drives don't need this. */ if (! ((ap->model[0] == 'N' && ap->model[1] == 'E') || ! (ap->model[0] == 'F' && ap->model[1] == 'X'))) bswap (ap->model, sizeof(ap->model)); bswap (ap->serial, sizeof(ap->serial)); bswap (ap->revision, sizeof(ap->revision)); --- 555,565 ---- /* * Shuffle string byte order. ! * Mitsumi, NEC and SHARP drives don't need this. */ if (! ((ap->model[0] == 'N' && ap->model[1] == 'E') || ! (ap->model[0] == 'F' && ap->model[1] == 'X') || ! (ap->model[0] == 'S' && ap->model[1] == 'H'))) bswap (ap->model, sizeof(ap->model)); bswap (ap->serial, sizeof(ap->serial)); bswap (ap->revision, sizeof(ap->revision)); Index: PAO/sys/i386/isa/atapi.h diff -c PAO/sys/i386/isa/atapi.h:1.1.1.4 PAO/sys/i386/isa/atapi.h:1.1.1.4.2.1 *** PAO/sys/i386/isa/atapi.h:1.1.1.4 Sat Dec 5 05:37:18 1998 --- PAO/sys/i386/isa/atapi.h Sun Dec 6 07:46:57 1998 *************** *** 279,284 **** --- 279,287 ---- #ifndef ATAPI_MODULE int atapi_attach (int ctlr, int unit, int port); + #ifdef ATAPI_DETACH + int atapi_detach (int ctlr, int unit, int port); + #endif #endif /* Index: PAO/sys/i386/isa/clock.c diff -c PAO/sys/i386/isa/clock.c:1.1.1.1 PAO/sys/i386/isa/clock.c:1.1.1.1.8.1 *** PAO/sys/i386/isa/clock.c:1.1.1.1 Thu Dec 11 22:36:55 1997 --- PAO/sys/i386/isa/clock.c Sun Dec 6 07:46:59 1998 *************** *** 483,488 **** --- 483,499 ---- return (0); } + int + sysbeep_cancel(void) + { + if (beeping) { + untimeout(sysbeepstop, (void *)NULL); + sysbeepstop((void *)NULL); + return 0; + } + return -1; + } + /* * RTC support routines */ *************** *** 625,630 **** --- 636,667 ---- write_eflags(ef); } + #if 1 /* XXX ncv port */ + unsigned int delaycount; + #define FIRST_GUESS 0x2000 + + static void + findcpuspeed() + { + int i; + int remainder; + + /* Put counter in count down mode */ + outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); + outb(TIMER_CNTR0, 0xff); + outb(TIMER_CNTR0, 0xff); + for (i = FIRST_GUESS; i; i--) + ; + /* Read the value left in the counter */ + remainder = getit(); + /* + * Formula for delaycount is: + * (loopcount * timer clock speed) / (counter ticks * 1000) + */ + delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff-remainder); + } + #endif /* ncv port */ + /* * Initialize 8253 timer 0 early so that it can be used in DELAY(). * XXX initialization of other timers is unintentionally left blank. *************** *** 634,639 **** --- 671,679 ---- { u_int delta, freq; + #if 1 /* XXX ncv port */ + findcpuspeed(); + #endif writertc(RTC_STATUSA, rtc_statusa); writertc(RTC_STATUSB, RTCSB_24HR); Index: PAO/sys/i386/isa/fd.c diff -c PAO/sys/i386/isa/fd.c:1.1.1.2 PAO/sys/i386/isa/fd.c:1.1.1.2.4.1 *** PAO/sys/i386/isa/fd.c:1.1.1.2 Fri Jul 24 19:17:25 1998 --- PAO/sys/i386/isa/fd.c Sun Dec 6 07:47:00 1998 *************** *** 5,10 **** --- 5,14 ---- * This code is derived from software contributed to Berkeley by * Don Ahn. * + * Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu) + * aided by the Linux floppy driver modifications from David Bateman + * (dbateman@eng.uts.edu.au). + * * Copyright (c) 1993, 1994 by * jc@irbs.UUCP (John Capo) * vak@zebub.msk.su (Serge Vakulenko) *************** *** 92,97 **** --- 96,105 ---- /* configuration flags */ #define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */ + #ifdef FDC_YE + #define FDC_IS_PCMCIA (1 << 1) /* if successful probe, then it's + a PCMCIA device */ + #endif /* internally used only, not really from CMOS: */ #define RTCFDT_144M_PRETENDED 0x1000 *************** *** 204,209 **** --- 212,222 ---- int ftattach(struct isa_device *, struct isa_device *, int); #endif + #ifdef FDC_YE + #include "card.h" + static int yeattach(struct isa_device *); + #endif + /* autoconfig functions */ static int fdprobe(struct isa_device *); static int fdattach(struct isa_device *); *************** *** 245,250 **** --- 258,266 ---- #define RECALWAIT 9 #define MOTORWAIT 10 #define IOTIMEDOUT 11 + #ifdef FDC_YE + #define PIOREAD 12 + #endif #ifdef FDC_DEBUG static char const * const fdstates[] = *************** *** 261,266 **** --- 277,285 ---- "RECALWAIT", "MOTORWAIT", "IOTIMEDOUT" + #ifdef FDC_YE + ,"PIOREAD" + #endif }; /* CAUTION: fd_debug causes huge amounts of logging output */ *************** *** 272,277 **** --- 291,392 ---- #define TRACE1(arg1, arg2) #endif /* FDC_DEBUG */ + #ifdef FDC_YE + #if NCARD > 0 + #include + #include + #include + #include + + /* + * PC-Card (PCMCIA) specific code. + */ + static int yeinit(struct pccard_devinfo *); /* init device */ + static void yeunload(struct pccard_devinfo *); /* Disable driver */ + static int yeintr(struct pccard_devinfo *); /* Interrupt handler */ + + static struct pccard_device ye_info = { + "fdc", + yeinit, + yeunload, + yeintr, + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + }; + + DATA_SET(pccarddrv_set, ye_info); + + /* + * this is the secret PIO data port (offset from base) + */ + #define FDC_YE_DATAPORT 6 + + /* + * Initialize the device - called from Slot manager. + */ + static int yeinit(struct pccard_devinfo *devi) + { + fdc_p fdc = &fdc_data[devi->isahd.id_unit]; + + /* validate unit number. */ + if (devi->isahd.id_unit >= NFDC) + return(ENODEV); + + fdc->baseport = devi->isahd.id_iobase; + + /* + * reset controller + */ + outb(fdc->baseport+FDOUT, 0); + DELAY(100); + outb(fdc->baseport+FDOUT, FDO_FRST); + + /* + * wire into system + */ + if (yeattach(&devi->isahd) == 0) + return(ENXIO); + + return(0); + } + + /* + * yeunload - unload the driver and clear the table. + * XXX TODO: + * This is usually called when the card is ejected, but + * can be caused by a modunload of a controller driver. + * The idea is to reset the driver's view of the device + * and ensure that any driver entry points such as + * read and write do not hang. + */ + static void yeunload(struct pccard_devinfo *devi) + { + + if (fd_data[devi->isahd.id_unit].type == NO_TYPE) + return; + + /* + * this prevents Fdopen() and fdstrategy() from attempting + * to access unloaded controller + */ + fd_data[devi->isahd.id_unit].type = NO_TYPE; + + printf("fdc%d: unload\n", devi->isahd.id_unit); + } + + /* + * yeintr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int yeintr(struct pccard_devinfo *devi) + { + fdintr((fdcu_t)devi->isahd.id_unit); + return(1); + } + #endif /* NCARD > 0 */ + #endif /* FDC_YE */ + + /* autoconfig structure */ struct isa_driver fdcdriver = { *************** *** 507,512 **** --- 622,635 ---- { return(0); } + #ifdef FDC_YE + /* + * don't succeed on probe; wait + * for PCCARD subsystem to do it + */ + if (dev->id_flags & FDC_IS_PCMCIA) + return(0); + #endif return (IO_FDCSIZE); } *************** *** 627,633 **** fdc->fdct = FDC_UNKNOWN; break; } ! if (fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN && enable_fifo(fdc) == 0) { printf("fdc%d: FIFO enabled", fdcu); --- 750,756 ---- fdc->fdct = FDC_UNKNOWN; break; } ! if (fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN && enable_fifo(fdc) == 0) { printf("fdc%d: FIFO enabled", fdcu); *************** *** 797,802 **** --- 920,1063 ---- return (1); } + #ifdef FDC_YE + /* + * this is a subset of fdattach() optimized for the Y-E Data + * PCMCIA floppy drive. + */ + static int yeattach(struct isa_device *dev) + { + fdcu_t fdcu = dev->id_unit; + fdc_p fdc = fdc_data + fdcu; + fdsu_t fdsu = 0; /* assume 1 drive per YE controller */ + fdu_t fdu; + fd_p fd; + int st0, st3, i; + #ifdef DEVFS + int mynor; + int typemynor; + int typesize; + #endif + + fdc->fdcu = fdcu; + /* + * the FDC_PCMCIA flag is used to to indicate special PIO is used + * instead of DMA + */ + fdc->flags = FDC_ATTACHED|FDC_PCMCIA; + fdc->state = DEVIDLE; + /* reset controller, turn motor off, clear fdout mirror reg */ + outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); + bufq_init(&fdc->head); + #if 0 + /* + * assume 2 drives/ "normal" controller + */ + fdu = fdcu * 2; + #else + fdu = fdcu; /* XXX use same unit number, between fdc and fd */ + #endif + if (fdu >= NFD) { + printf("fdu %d >= NFD\n",fdu); + return(0); + }; + fd = &fd_data[fdu]; + + set_motor(fdcu, fdsu, TURNON); + DELAY(1000000); /* 1 sec */ + fdc->fdct = FDC_NE765; + + if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && + (st3 & NE7_ST3_T0)) { + /* if at track 0, first seek inwards */ + /* seek some steps: */ + (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); + DELAY(300000); /* ...wait a moment... */ + (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ + } + + /* If we're at track 0 first seek inwards. */ + if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { + /* Seek some steps... */ + if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { + /* ...wait a moment... */ + DELAY(300000); + /* make ctrlr happy: */ + (void)fd_sense_int(fdc, 0, 0); + } + } + + for(i = 0; i < 2; i++) { + /* + * we must recalibrate twice, just in case the + * heads have been beyond cylinder 76, since most + * FDCs still barf when attempting to recalibrate + * more than 77 steps + */ + /* go back to 0: */ + if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) { + /* a second being enough for full stroke seek*/ + DELAY(i == 0? 1000000: 300000); + + /* anything responding? */ + if (fd_sense_int(fdc, &st0, 0) == 0 && + (st0 & NE7_ST0_EC) == 0) + break; /* already probed succesfully */ + } + } + + set_motor(fdcu, fdsu, TURNOFF); + + if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ + return(0); + + fd->track = FD_NO_TRACK; + fd->fdc = fdc; + fd->fdsu = fdsu; + fd->options = 0; + printf("fdc%d: 1.44MB 3.5in PCMCIA\n", fdcu); + fd->type = FD_1440; + + #ifdef DEVFS + mynor = fdcu << 6; + fd->bdevs[0] = devfs_add_devswf(&fd_bdevsw, mynor, DV_BLK, + UID_ROOT, GID_OPERATOR, 0640, + "fd%d", fdu); + fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, + UID_ROOT, GID_OPERATOR, 0640, + "rfd%d", fdu); + /* + * XXX this and the lookup in Fdopen() should be + * data driven. + */ + typemynor = mynor | FD_1440; + typesize = fd_types[FD_1440 - 1].size / 2; + /* + * XXX all these conversions give bloated code and + * confusing names. + */ + if (typesize == 1476) + typesize = 1480; + if (typesize == 1722) + typesize = 1720; + fd->bdevs[FD_1440] = devfs_add_devswf(&fd_bdevsw, typemynor, + DV_BLK, UID_ROOT, GID_OPERATOR, + 0640, "fd%d.%d", fdu, typesize); + fd->cdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor, + DV_CHR, UID_ROOT, GID_OPERATOR, + 0640,"rfd%d.%d", fdu, typesize); + for (i = 0; i < MAXPARTITIONS; i++) { + fd->bdevs[1 + NUMDENS + i] = devfs_link(fd->bdevs[0], + "fd%d%c", fdu, 'a' + i); + fd->cdevs[1 + NUMDENS + i] = devfs_link(fd->cdevs[0], + "rfd%d%c", fdu, 'a' + i); + } + #endif /* DEVFS */ + + return (1); + } + #endif + /****************************************************************************/ /* motor control stuff */ /* remember to not deselect the drive we're working on */ *************** *** 812,818 **** fdout |= (FDO_MOEN0 << fdsu) + fdsu; } else fdout &= ~(FDO_MOEN0 << fdsu); - if(!turnon && (fdout & (FDO_MOEN0+FDO_MOEN1+FDO_MOEN2+FDO_MOEN3)) == 0) /* gonna turn off the last drive, put FDC to bed */ --- 1073,1078 ---- *************** *** 1108,1113 **** --- 1368,1384 ---- fd = &fd_data[fdu]; fdc = fd->fdc; fdcu = fdc->fdcu; + #ifdef FDC_YE + if (fd->type == NO_TYPE) { + bp->b_error = ENXIO; + bp->b_flags |= B_ERROR; + /* + * I _refuse_ to use a goto + */ + biodone(bp); + return; + }; + #endif #if NFT > 0 if (FDTYPE(minor(bp->b_dev)) & F_TAPE_TYPE) { *************** *** 1282,1287 **** --- 1553,1590 ---- ; } + #ifdef FDC_YE + /* + * magic pseudo-DMA initialization for YE FDC. Sets count and + * direction + */ + #define SET_BCDR(wr,cnt,port) outb(port,(((cnt)-1) & 0xff)); \ + outb(port+1,((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f))) + + /* + * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy + */ + static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) + { + u_char *cptr = (u_char *)addr; + fdc_p fdc = &fdc_data[fdcu]; + int io = fdc->baseport; + + if (flags & B_READ) { + if (fdc->state != PIOREAD) { + fdc->state = PIOREAD; + return(0); + }; + SET_BCDR(0,count,io); + insb(io+FDC_YE_DATAPORT,cptr,count); + } else { + outsb(io+FDC_YE_DATAPORT,cptr,count); + SET_BCDR(0,count,io); + }; + return(1); + } + #endif /* FDC_YE */ + /***********************************************************************\ * The controller state machine. * * if it returns a non zero value, it should be called again immediatly * *************** *** 1466,1471 **** --- 1769,1777 ---- } fd->track = b_cylinder; + #ifdef FDC_YE + if (!(fdc->flags & FDC_PCMCIA)) + #endif isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); sectrac = fd->ft->sectrac; *************** *** 1507,1512 **** --- 1813,1824 ---- if(format) { /* formatting */ + #ifdef FDC_YE + if (fdc->flags & FDC_PCMCIA) + (void)fdcpio(fdcu,bp->b_flags, + bp->b_un.b_addr+fd->skip, + bp->b_bcount); + #endif if(fd_cmd(fdcu, 6, NE7CMD_FORMAT, head << 2 | fdu, *************** *** 1523,1528 **** --- 1835,1857 ---- } else { + #ifdef FDC_YE + if (fdc->flags & FDC_PCMCIA) { + /* + * this seems to be necessary even when + * reading data + */ + SET_BCDR(1,fdblk,fdc->baseport); + + /* + * perform the write pseudo-DMA before + * the WRITE command is sent + */ + if (!read) + (void)fdcpio(fdcu,bp->b_flags, + bp->b_un.b_addr+fd->skip,fdblk); + }; + #endif if (fd_cmd(fdcu, 9, (read ? NE7CMD_READ : NE7CMD_WRITE), head << 2 | fdu, /* head & unit */ *************** *** 1540,1563 **** return(retrier(fdcu)); } } fdc->state = IOCOMPLETE; timeout(fd_timeout, (caddr_t)fdcu, hz); return(0); /* will return later */ case IOCOMPLETE: /* IO DONE, post-analyze */ untimeout(fd_timeout, (caddr_t)fdcu); - if (fd_read_status(fdc, fd->fdsu)) { if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ return retrier(fdcu); } - fdc->state = IOTIMEDOUT; /* FALLTHROUGH */ case IOTIMEDOUT: isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->status[0] & NE7_ST0_IC) --- 1869,1920 ---- return(retrier(fdcu)); } } + #ifdef FDC_YE + if (fdc->flags & FDC_PCMCIA) + /* + * if this is a read, then simply await interrupt + * before performing PIO + */ + if (read && !fdcpio(fdcu,bp->b_flags, + bp->b_un.b_addr+fd->skip,fdblk)) { + timeout(fd_timeout, (caddr_t)fdcu, hz); + return(0); /* will return later */ + }; + + /* + * write (or format) operation will fall through and + * await completion interrupt + */ + #endif fdc->state = IOCOMPLETE; timeout(fd_timeout, (caddr_t)fdcu, hz); return(0); /* will return later */ + #ifdef FDC_YE + case PIOREAD: + /* + * cancel timeout and actually perform the PIO read + */ + untimeout(fd_timeout, (caddr_t)fdcu); + (void)fdcpio(fdcu,bp->b_flags,bp->b_un.b_addr+fd->skip,fdblk); + fdc->state = IOCOMPLETE; + /* FALLTHROUGH */ + #endif case IOCOMPLETE: /* IO DONE, post-analyze */ untimeout(fd_timeout, (caddr_t)fdcu); if (fd_read_status(fdc, fd->fdsu)) { if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ return retrier(fdcu); } fdc->state = IOTIMEDOUT; /* FALLTHROUGH */ case IOTIMEDOUT: + #ifdef FDC_YE + if (!(fdc->flags & FDC_PCMCIA)) + #endif isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->status[0] & NE7_ST0_IC) Index: PAO/sys/i386/isa/fdc.h diff -c PAO/sys/i386/isa/fdc.h:1.1.1.1 PAO/sys/i386/isa/fdc.h:1.1.1.1.10.1 *** PAO/sys/i386/isa/fdc.h:1.1.1.1 Thu Dec 11 22:36:55 1997 --- PAO/sys/i386/isa/fdc.h Sun Dec 6 07:47:01 1998 *************** *** 55,60 **** --- 55,64 ---- #define FDC_TAPE_BUSY 0x04 #define FDC_STAT_VALID 0x08 #define FDC_HAS_FIFO 0x10 + #ifdef FDC_YE + #define FDC_PCMCIA 0x20 + #define FDC_UNLOADED 0x40 + #endif struct fd_data *fd; int fdu; /* the active drive */ int state; Index: PAO/sys/i386/isa/hss.c diff -c /dev/null PAO/sys/i386/isa/hss.c:1.1.8.1 *** /dev/null Fri Dec 25 10:50:48 1998 --- PAO/sys/i386/isa/hss.c Sun Dec 6 07:47:04 1998 *************** *** 0 **** --- 1,837 ---- + /* + * Copyright (c) 1995,1996,1997 Jun-ichiro Itoh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jun-ichiro Itoh. + * 4. The name of Jun-ichiro Itoh may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /* + * Hitachi microcomputer system Speech Synthesis card (MSSHVPC02E) driver + * + * To purchasing the card, contact the following address: + * Tokyo office, Hitachi microcomputer system co. + * J tower 9th floor, 1-1, Higane-machi, + * Fuchu, Tokyo 183 JAPAN + * (voice) +81-423-51-6600 / (fax) +81-423-51-6601 + */ + /* + * Special thanks to: Yasuhito riho-m Watanabe + */ + + #include + #include + #include + #include + #include + #include + + #include + + #include + #ifdef PC98 + #include + #else /*PC98*/ + #include + #endif /*PC98*/ + #ifdef __bsdi__ + #include + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + #include + #endif /*__FreeBSD__*/ + + /* OS dependent part */ + #ifdef __bsdi__ + #include "cs.h" + #if NCS > 0 + #define PCCARD_BSDI + #endif + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + #include "card.h" + #if NCARD > 0 + #define PCCARD_FREEBSD + #endif + #endif /*__FreeBSD__*/ + + #ifdef PCCARD_BSDI + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #endif /*PCCARD_BSDI*/ + #ifdef PCCARD_FREEBSD + #include + #include + #include + #endif /*PCCARD_FREEBSD*/ + + #ifdef __bsdi__ + #include "hssvar.h" + #endif + #ifdef __FreeBSD__ + #include + #include "hss.h" + #endif + + #if defined(PCCARD_BSDI) || defined(PCCARD_FREEBSD) + + #define CCPROBE_DEBUG + #define CCVERBOSE + #define TIMODEBUG + + #ifdef CCPROBE_DEBUG + int hss_ccprobe_debug = 0; + # define ccdprintf(x) { if (hss_ccprobe_debug) printf x; } + #else + # define ccdprintf(x) + #endif + + #ifdef CCVERBOSE + int hss_ccverbose = 0; + # define ccvprintf(x) { if (hss_ccverbose) printf x; } + #else + # define ccvprintf(x) + #endif + + #define TIMOMAX (1000000L) + #ifdef TIMODEBUG + int hss_timodebug = 0; + # define timoprintf(x) { if (hss_timodebug) printf x; } + #else + # define timoprintf(x) + #endif + + #endif /*PCCARD_BSDI || PCCARD_FREEBSD*/ + + int hssopen __P((dev_t, int, int, struct proc *)); + int hssread __P((dev_t, struct uio *, int)); + int hsswrite __P((dev_t, struct uio *, int)); + int hssclose __P((dev_t, int, int, struct proc *)); + #if 0 + int hssmap __P((dev_t, int, int)); + #endif + + #ifdef __bsdi__ + int hssprobe __P((struct device *, struct cfdata *, void *)); + void hssattach __P((struct device *, struct device *, void *)); + + struct cfdriver hsscd = + { NULL, "hss", hssprobe, hssattach, DV_DULL, sizeof(struct hss_softc) }; + + struct devsw hsssw = { + &hsscd, + hssopen, hssclose, hssread, hsswrite, noioctl, seltrue, nommap, + nostrat, nodump, nopsize, 0, + nostop + }; + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + int hss_isa_probe __P((struct isa_device *)); + int hss_isa_attach __P((struct isa_device *)); + + struct isa_driver hssdriver = + { hss_isa_probe, hss_isa_attach, "hss", 0 }; + + #define CDEV_MAJOR 81 + static struct cdevsw hsssw = { + hssopen, hssclose, hssread, hsswrite, + noioctl, nostop, noreset, nodevtotty, + seltrue, nommap, NULL, "hss", + NULL, -1, + }; + #endif /*__FreeBSD__*/ + + #define LBSZ 132 /*small local buffer in hsswrite()*/ + + #ifdef PCCARD_BSDI + + /* + * PCMCIA Card Service event handler (callback) + */ + hss_cse_handler(clidata, func, sock, info, mtdreq, buf, misc) + void *clidata; + int func, sock, info; + struct mtdreq *mtdreq; + char *buf; + int misc; + { + struct hss_softc *hssp = (struct hss_softc *)clidata; + + switch (func) { + case CSE_CARD_INSERTION: + if (hssp->hss_configured || cu_configured(&hssp->hss_clihdl, sock)) + break; + + if (hss_cc_probe(hssp, sock)) { + ccdprintf(("hss_cse_handler: probe okay\n")); + hss_cc_attach(hssp, sock); + } + break; + + case CSE_CARD_REMOVAL: + if (hssp->hss_configured && hssp->hss_rcfg.cscfg_Socket == sock) + hss_cc_detach(hssp, sock); + break; + + case CSE_CLIENT_INFO: + break; + + default: + break; + } + } + + /* + * probe the card. + */ + hss_cc_probe(hssp, socket) + struct hss_softc *hssp; + int socket; + { + if (cs_spec_lookup(socket, "hss", NULL, 0) != 0) { + return 0; + } + return 1; + #if 0 + cs_rtpl_t tplreq; + int unit = hssp->sc_dev.dv_unit; + int err; + int i; + + /* consult CISTPL_VERS_1 */ + tplreq.Socket = socket; + tplreq.Desired = CISTPL_VERS_1; + tplreq.TupleData = hssp->hss_vstr; + tplreq.TupleDataMax = sizeof(hssp->hss_vstr); + + if (err = cs_GetTuple(&tplreq)) { + if (err != CSERR_NO_MORE_ITEMS) + printf("hss%d: GetTuple(VERS_1) err 0x%x\n", unit, err); + return 0; + } + + hssp->hss_vlen = TupleLen(tplreq); + + #ifdef CCPROBE_DEBUG + if (hss_ccprobe_debug) { + printf("hss_cc_probe: "); + cu_print_version(hssp->hss_vstr, hssp->hss_vlen); + printf("\n"); + } + #endif + + /* since we don't have FUNCID, we sorely rely upon VERS_1 tuple. */ + if (bcmp(hssp->hss_vstr, hss_vstr, sizeof (hss_vstr)) == 0) { + #ifdef CCPROBE_DEBUG + if (hss_ccprobe_debug) { + printf("hss%d: ", unit); + cu_print_version(hssp->hss_vstr, hssp->hss_vlen); + printf("\n"); + } + #endif + + return 1; + } + + return 0; + #endif + } + + hss_cc_attach(hssp, socket) + struct hss_softc *hssp; + int socket; + { + cs_rtpl_t tplreq; + struct tpce tpce; + struct tpcc tpcc; + int unit = hssp->sc_dev.dv_unit; + u_char tplbuf[256]; + int err; + int i; + + ccdprintf(("hss_cc_attach: socket %d\n", socket)); + + /* + * CISTPL_CONF + */ + tplreq.Socket = socket; + tplreq.Desired = CISTPL_CONF; + tplreq.TupleData = tplbuf; + tplreq.TupleDataMax = sizeof(tplbuf); + + if (err = cs_GetTuple(&tplreq)) { + ccdprintf(("hss_cc_attach: no CISTPL_CONF, err 0x%x\n", err)); + return 0; + } + + if (err = cu_parse_conf(tplbuf, TupleLen(tplreq), &tpcc)) { + ccdprintf(("hss_cc_attach: bad CISTPL_CONF, err 0x%x\n", err)); + return 0; + } + + ccdprintf(("hss_cc_attach: radr 0x%x, rmsk 0x%x, last 0x%x\n", + tpcc.tpcc_radr, tpcc.tpcc_rmsk[0], tpcc.tpcc_last)); + + /* + * CISTPL_CE (must follow CISTPL_CONF) + */ + tplreq.Desired = CISTPL_CE; + + while ((err = cs_GetNextTuple(&tplreq)) == 0) { + tplreq.TupleData = tplbuf; + tplreq.TupleDataMax = sizeof(tplbuf); + if (err = cs_GetTupleData(&tplreq)) { + printf("hss_cc_attach: bad read on CISTPL_CE\n"); + return 0; + } + + cu_parse_ce(tplbuf, TupleLen(tplreq), &tpce, NULL); + #if 0 + cu_dump_ce(&tpce); + + printf("iftype: %d(%d) addrline: %d iocount: %d base: %x len:%x\n", + tpce.ce.ce_if_type, + TPCE_IF_TYPE_IO, + tpce.ce.ce_io_addrline, + tpce.ce.ce_io_count, + tpce.ce.ce_io[0].tpce_io_base, + tpce.ce.ce_io[0].tpce_io_len); + #endif + + if (tpce.ce.ce_if_type != TPCE_IF_TYPE_IO) + continue; + + /* + * If the card has proper cis-tuple, "proper version" + * However, Version 1.0 card requests 256 (1<<8) I/O + * addresses. How stupid it is. + */ + #if 1 + /*screwed up cis-tuple version*/ + { + static caddr_t baseaddrs[] = { + (caddr_t)0x320, (caddr_t)0x300, (caddr_t)0x310, + (caddr_t)0x330, (caddr_t)0x340, (caddr_t)0x200, + (caddr_t)0x3d0, + }; + size_t i; + + for (i = 0; i < sizeof(baseaddrs)/sizeof(baseaddrs[0]); i++) { + hssp->hss_rio.csrio_Socket = socket; + hssp->hss_rio.csrio_PortAttr1 = 0; + hssp->hss_rio.csrio_PortAttr2 = 0; + hssp->hss_rio.csrio_BasePort1 = baseaddrs[i]; + hssp->hss_rio.csrio_NumPorts1 = 16; + + ccdprintf(("hss%d: trying 0x%x len 0x%d\n", unit, + hssp->hss_rio.csrio_BasePort1, + hssp->hss_rio.csrio_NumPorts1)); + + if ((err = cs_RequestIO(&hssp->hss_clihdl, + &hssp->hss_rio)) == 0) + goto found; + } + } + #else + /*proper version*/ + if (tpce.ce.ce_io_addrline) { + hssp->hss_rio.csrio_BasePort1 = 0; + hssp->hss_rio.csrio_NumPorts1 = + (1 << tpce.ce.ce_io_addrline); + hssp->hss_rio.csrio_IOAddrLines = + tpce.ce.ce_io_addrline; + } else if (tpce.ce.ce_io_count == 1) { + hssp->hss_rio.csrio_BasePort1 = + tpce.ce.ce_io[0].tpce_io_base; + hssp->hss_rio.csrio_NumPorts1 = + tpce.ce.ce_io[0].tpce_io_len; + } else + continue; + + hssp->hss_rio.csrio_Socket = socket; + hssp->hss_rio.csrio_PortAttr1 = 0; + hssp->hss_rio.csrio_PortAttr2 = 0; + + ccdprintf(("hss%d: trying 0x%x len 0x%d\n", unit, + hssp->hss_rio.csrio_BasePort1, + hssp->hss_rio.csrio_NumPorts1)); + + if ((err = cs_RequestIO(&hssp->hss_clihdl, + &hssp->hss_rio)) == 0) + goto found; + #endif + } + + if (err) { + printf("hss_cc_attach: error finding usable CISTPL_CE\n"); + return 0; + } + + found:; + hssp->hss_io_addr = (caddr_t)hssp->hss_rio.csrio_BasePort1; + hssp->hss_io_size = hssp->hss_rio.csrio_NumPorts1; + + /* + * configure the card. should consult CISTPL_DEVICE + */ + hssp->hss_rcfg.cscfg_Socket = socket; + hssp->hss_rcfg.cscfg_Attributes = 0; /* we don't need IRQ */ + hssp->hss_rcfg.cscfg_Vcc = 50; /* 5V to Vcc, Vpp1, Vpp2 */ + hssp->hss_rcfg.cscfg_Vpp1 = 50; + hssp->hss_rcfg.cscfg_Vpp2 = 50; + hssp->hss_rcfg.cscfg_IntType = 2; /* fake: I/O card */ + hssp->hss_rcfg.cscfg_Present = CREGMAP_COR; + hssp->hss_rcfg.cscfg_ConfigBase = tpcc.tpcc_radr; + hssp->hss_rcfg.cscfg_ConfigIndex = tpce.ce.ce_index; + + if (err = cs_RequestConfiguration(&hssp->hss_clihdl, &hssp->hss_rcfg)) { + ccdprintf(("hss_cc_attach: RequestConfig err 0x%x\n", err)); + cs_ReleaseIO(&hssp->hss_clihdl, &hssp->hss_rio); + return 0; + } + hssp->hss_configured = 1; + + #if 0 + /* + * allocate memory window + */ + rwin.Socket = socket; + rwin.Attributes = CSRWIN_ENABLE|CSRWIN_DATA_PATH_16; + rwin.Base = 0; /* pick available address */ + rwin.Size = 4096; /* map 4Kbytes */ + rwin.AccessSpeed = 4; /* 100nsec, based on CISTPL_DEVICE */ + if (err = cs_RequestWindow(&hssp->hss_clihdl, &hssp->hss_whdl, &rwin)) { + printf("hss_cc_attach: can't alloc 16-bit win. err 0x%x\n", err); + goto bad; + } + + /* + * map card memory onto the memory window + */ + rpage.CardOffset = 0; + rpage.Page = 0; + if (err = cs_MapMemPage(&hssp->hss_clihdl, &hssp->hss_whdl, &rpage)) { + printf("hss_cc_attach: can't map 16-bit win. err 0x%x\n", err); + goto bad; + } + + hssp->hss_mem_addr = (caddr_t) rwin.Base; + hssp->hss_mem_size = rwin.Size; + + ccdprintf(("hss_cc_attach: got 16-bit win @ 0x%x (phys 0x%x)\n", + cs_ptokvm(rwin.Base), rwin.Base)); + #endif + + ccvprintf(("hss%d: <%s> iobase 0x%x\n", unit, + cu_EditTuple(hssp->hss_vstr, hssp->hss_vlen, 40), + hssp->hss_io_addr)); + + return 1; + + bad:; + hss_cc_detach(hssp, socket); + return 0; + } + + hss_cc_detach(hssp, socket) + struct hss_softc *hssp; + int socket; + { + if (hssp->hss_configured) { + cs_ReleaseConfiguration(&hssp->hss_clihdl, &hssp->hss_rcfg); + cs_ReleaseIO(&hssp->hss_clihdl, &hssp->hss_rio); + hssp->hss_configured = 0; + } + + #if 0 + if (hssp->hss_whdl) { + cs_ReleaseWindow(&hssp->hss_clihdl, &hssp->hss_whdl); + hssp->hss_whdl = 0; + } + #endif + } + + #endif /*PCCARD_BSDI*/ + + #ifdef PCCARD_FREEBSD + + #include "apm.h" + #include + #include + #include + #include + + /* + * PC-Card (PCMCIA) specific code. + */ + static int card_intr __P((struct pccard_devinfo *)); + static void hss_unload __P((struct pccard_devinfo *)); + static int hss_pccard_init __P((struct pccard_devinfo *)); + static int hss_pccard_attach __P((struct pccard_devinfo *)); + + static struct pccard_device hss_info = { + "hss", + hss_pccard_init, + hss_unload, + card_intr, + 0, /* Attributes - presently unused */ + &bio_imask /* usual device */ + }; + + DATA_SET(pccarddrv_set, hss_info); + + static struct hss_softc *hss_softc[NHSS]; + + /* + * + */ + static int + hss_pccard_init(devi) + struct pccard_devinfo *devi; + { + struct hss_softc *sc = hss_softc[devi->pd_unit]; + int i; + dev_t dev; + + if (NHSS <= devi->pd_unit) + return ENXIO; + if (!sc) { + sc = (struct hss_softc *) malloc(sizeof(struct hss_softc), + M_DEVBUF, M_NOWAIT); + if (!sc) { + printf("hss%d: cannot alloc hss_softc.\n", devi->pd_unit); + return ENXIO; + } + bzero(sc, sizeof(struct hss_softc)); + hss_softc[devi->pd_unit] = sc; + } + sc->hss_io_addr = (caddr_t)devi->pd_iobase; + sc->hss_io_size = 16; /*XXX*/ + sc->hss_configured = 0; /* just for initialize */ + + /* attach routine: we need nothing at all */ + printf("hss%d: initialized.\n", devi->pd_unit); + + dev = makedev(CDEV_MAJOR, 0); + printf("cdevsw_add returns %d\n", cdevsw_add(&dev, &hsssw, NULL)); + + sc->hss_configured = 1; + + return 0; + } + + static int + hss_pccard_attach(devi) + struct pccard_devinfo *devi; + { + struct hss_softc *sc = hss_softc[devi->pd_unit]; + + if (NHSS <= devi->pd_unit) + return ENXIO; + sc->hss_io_addr = (caddr_t)devi->pd_iobase; + sc->hss_io_size = 8; + + return 1; + } + + static void + hss_unload(devi) + struct pccard_devinfo *devi; + { + struct hss_softc *sc = hss_softc[devi->pd_unit]; + + if (NHSS <= devi->pd_unit) + return; + if (!sc->hss_configured) { + printf("hss%d: already unloaded\n", devi->pd_unit); + return; + } + sc->hss_configured = 0; + printf("hss%d: unload\n", devi->pd_unit); + } + + /* + * card_intr - Shared interrupt called from front end of PC-Card handler. + */ + static int + card_intr(devi) + struct pccard_devinfo *devi; + { + return 0; /*we don't handle interrupts*/ + } + + #endif /*PCCARD_FREEBSD*/ + + /* + * Normal init routine called by configure() code + */ + #ifdef __bsdi__ + /* ARGSUSED */ + int + hssprobe(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; + { + register struct isa_attach_args *ia = (struct isa_attach_args *)aux; + + ia->ia_iobase = 0; + ia->ia_iosize = 0; + ia->ia_irq = IRQNONE; + return 1; + } + + /* ARGSUSED */ + void + hssattach(parent, self, aux) + struct device *parent, *self; + void *aux; + { + register struct hss_softc *hssp = (struct hss_softc *)self; + cs_rclient_t rcli; + int i; + + #if 0 + hssp->hss_whdl = 0; + hssp->hss_mem_addr = 0; + #endif + hssp->hss_configured = 0; + + /* + * initialize as card client + */ + rcli.Attributes = CSCLI_IO; /*XXX*/ + rcli.EventMask = ~CSEM_CD_CHANGE; + rcli.CallBack = hss_cse_handler; + rcli.CallBackArg = hssp; + + cs_RegisterClient(&hssp->hss_clihdl, &rcli); + + isa_establish(&hssp->sc_id, &hssp->sc_dev); + printf(": PCCARD_BSDI Speech Synthesizer\n"); + } + #endif /*__bsdi__*/ + + #ifdef __FreeBSD__ + int + hss_isa_probe(id) + struct isa_device *id; + { + return 0; /*always fail*/ + } + + int + hss_isa_attach(id) + struct isa_device *id; + { + return 0; /*always fail*/ + } + #endif /*__FreeBSD__*/ + + int + hssopen(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; + { + int unit = HSSUNIT(dev); + register struct hss_softc *hssp; + + /* Validate unit number */ + #ifdef __bsdi__ + if (unit >= hsscd.cd_ndevs || (hssp = hsscd.cd_devs[unit]) == NULL) + return (ENXIO); + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + if (NHSS <= unit || (hssp = hss_softc[unit]) == NULL) + return (ENXIO); + #endif /*__FreeBSD__*/ + #if defined(PCCARD_BSDI) || defined(PCCARD_FREEBSD) + if (! hssp->hss_configured) + return ENXIO; + #endif + if (hssp->hss_flags & HSS_OPEN) + return (EBUSY); + /* + * First open. + */ + hssp->hss_flags |= HSS_OPEN; + + if (suser(p->p_ucred, &p->p_acflag) == 0) + hssp->hss_flags |= HSS_PRIV; + + return (0); + } + + /*ARGSUSED*/ + int + hssread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; + { + int error; + u_char buffer[1]; + int unit = HSSUNIT(dev); + #ifdef __bsdi__ + register struct hss_softc *sc = hsscd.cd_devs[HSSUNIT(dev)]; + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + register struct hss_softc *sc = hss_softc[HSSUNIT(dev)]; + #endif /*__FreeBSD*/ + caddr_t base = sc->hss_io_addr; + + buffer[0] = inb((int)base + HSS_PORTB); + error = uiomove(buffer, 1, uio); + if (error) + return error; + + return 0; + } + + /*ARGSUSED*/ + int + hsswrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; + { + int n, i, error; + u_char s0, s1, s2; + long timo; + int timeoutcnt; + int timeerrcnt; + u_char buffer[LBSZ]; + int unit = HSSUNIT(dev); + #ifdef __bsdi__ + register struct hss_softc *sc = hsscd.cd_devs[HSSUNIT(dev)]; + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + register struct hss_softc *sc = hss_softc[HSSUNIT(dev)]; + #endif /*__FreeBSD*/ + caddr_t base = sc->hss_io_addr; + + /* Loop while more data remaining to be written */ + while ((n = min(LBSZ, uio->uio_resid)) > 0) { + timeoutcnt = 0; + timeerrcnt = 0; + + error = uiomove(buffer, n, uio); + if (error) + return error; + + for (i = 0; i < n; i++) { + timoprintf(("buf=%d, i=%d, %d chars to go\n", + n, i, n-i)); + #if 1 + /*busywait version*/ + s0 = inb((int)base + HSS_PORTB); + outb((int)base + HSS_PORTC, buffer[i]); + outb((int)base + HSS_SHIRQ, 0); + + timoprintf(("entering timo1\n")); + timo = 0L; + do { + if (TIMOMAX < ++timo) { + timoprintf(("timo1 timeouted\n")); + goto timeout; + } + s1 = s2; + s2 = inb((int)base + HSS_PORTB); + } while (s0 == s2 || s1 != s2); + timoprintf(("timo1=%ld\n", timo)); + + if (s2 == 0x90) + timeerrcnt++; + + if (0) { + timeout:; + timeoutcnt++; + } + #else + /*write-and-forget version*/ + outb((int)base + HSS_PORTC, buffer[i]); + outb((int)base + HSS_HSIRQ, 0); + #endif + } + + /* error reporting... */ + if (timeerrcnt || timeoutcnt) { + printf("hss%d: hsswrite timeerr=%d, timeout=%d in %d chars\n", + unit, timeerrcnt, timeoutcnt, n); + } + } + + return 0; + } + + /*ARGSUSED*/ + int + hssclose(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; + { + #ifdef __bsdi__ + struct hss_softc *hssp = hsscd.cd_devs[HSSUNIT(dev)]; + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + struct hss_softc *hssp = hss_softc[HSSUNIT(dev)]; + #endif /*__FreeBSD*/ + + hssp->hss_flags = HSS_DEAD; + return (0); + } + + #if 0 + /*ARGSUSED*/ + int + hssmap(dev, off, prot) + dev_t dev; + int off, prot; + { + #ifdef __bsdi__ + struct hss_softc *hssp = hsscd.cd_devs[HSSUNIT(dev)]; + #endif /*__bsdi__*/ + #ifdef __FreeBSD__ + struct hss_softc *hssp = hss_softc[HSSUNIT(dev)]; + #endif /*__FreeBSD*/ + u_int paddr; + + if (off + NBPG > hssp->hss_mem_size) + return (-1); + return (((u_int)hssp->hss_mem_addr + off) >> PGSHIFT); + } + #endif Index: PAO/sys/i386/isa/hssvar.h diff -c /dev/null PAO/sys/i386/isa/hssvar.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:49 1998 --- PAO/sys/i386/isa/hssvar.h Sun Dec 6 07:47:08 1998 *************** *** 0 **** --- 1,79 ---- + /* + * Copyright (c) 1995,1996,1997 Jun-ichiro Itoh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jun-ichiro Itoh. + * 4. The name of Jun-ichiro Itoh may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /* + * Hitachi microcomputer system Speech Synthesis card (MSSHVPC02E) driver + * + * To purchasing the card, contact the following address: + * Tokyo office, Hitachi microcomputer system co. + * J tower 9th floor, 1-1, Higane-machi, + * Fuchu, Tokyo 183 JAPAN + * (voice) +81-423-51-6600 / (fax) +81-423-51-6601 + */ + /* + * Special thanks to: Yasuhito riho-m Watanabe + */ + + struct hss_softc { + #ifdef __bsdi__ + struct device sc_dev; /* base device */ + struct isadev sc_id; /* ISA device */ + #endif /*__bsdi__*/ + int hss_flags; /* software flags */ + caddr_t hss_io_addr; /* hss io addr */ + int hss_io_size; /* hss io addr */ + #if 0 + caddr_t hss_mem_addr; /* hss memory addr */ + int hss_mem_size; /* hss memory size */ + #endif + #ifdef PCCARD_BSDI + CliHandle_t hss_clihdl; + cs_cfg_t hss_rcfg; + int hss_configured; + u_char hss_vstr[255]; /* VERS_1 tuple */ + int hss_vlen; /* VERS_1 tuple */ + cs_rio_t hss_rio; + #if 0 + WinHandle_t hss_whdl; /* memwin for chip registers */ + #endif + #endif /*PCCARD_BSDI*/ + #ifdef PCCARD_FREEBSD + int hss_configured; + #endif /*PCCARD_FREEBSD*/ + }; + + #define HSS_DEAD 0x00 + #define HSS_OPEN 0x02 + #define HSS_PRIV 0x04 + + #define HSS_PORTB 0x0002 + #define HSS_PORTC 0x0002 + #define HSS_SHIRQ 0x000C + + #define HSSUNIT(d) ((d) & 0x7) Index: PAO/sys/i386/isa/if_cnw.c diff -c /dev/null PAO/sys/i386/isa/if_cnw.c:1.1.8.1 *** /dev/null Fri Dec 25 10:50:49 1998 --- PAO/sys/i386/isa/if_cnw.c Sun Dec 6 07:47:10 1998 *************** *** 0 **** --- 1,2055 ---- + /* + * Copyright (c) 1996, 1997 Berkeley Software Design, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that this notice is retained, + * the conditions in the following notices are met, and terms applying + * to contributors in the following notices also apply to Berkeley + * Software Design, Inc. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by + * Berkeley Software Design, Inc. + * 4. Neither the name of the Berkeley Software Design, Inc. nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * BSDI $Id: if_cnw.c,v 1.1.8.1 1998/12/05 22:47:10 itojun Exp $ + * + * Paul Borman, December 1996 + * + * This driver is derived from a generic frame work which is + * Copyright(c) 1994,1995,1996 + * Yoichi Shinoda, Yoshitaka Tokugawa, WIDE Project, Wildboar Project + * and Foretune. All rights reserved. + * + * A linux driver was used as the "hardware reference manual" (i.e., + * to determine registers and a general outline of how the card works) + * That driver is publically available and copyright + * + * John Markus Bj,Ax(Brndalen + * Department of Computer Science + * University of Troms,Ax(B + * Norway + * johnm@staff.cs.uit.no, http://www.cs.uit.no/~johnm/ + */ + + /* + * Netwave AirSurfer Wireless LAN + * (Formerly known as the Xircom CreditCard Netwave Adapter) + */ + + #if defined(__FreeBSD__) + /* + * FreeBSD port to use with PAO by Kenjiro Cho . + * Fred L. Templin modified pccardd to support + * card_mem flags and multiple card_mem entries. + */ + #include "cnw.h" + #endif + #if !defined(__FreeBSD__) || NCNW > 0 + /* + * Keep track of the last 128 packets sent/received, along with status. + * Only used to help determine timing related optimizations. + #define CNW_TRAIL + */ + + /* + * Display each packet on the console as it is received. + * This is only for hard core debugging. + #define RECV_PKT_DEBUG + */ + + /* + * The card appears to work much better when we only allow one packet + * "in the air" at a time. This is done by not allowing another packet + * on the card, even if there is room. Turning this off will allow the + * driver to stuff packets on the card as soon as a transmit buffer is + * available. This does increase the number of collisions, though. + * We can que a second packet if there are transmit buffers available, + * but we do not actually send the packet until the last packet has + * been written. + */ + #define ONE_AT_A_TIME + + /* + * Use internal (slow) versions of bcmp and bcopy. These are declared + * as volatile too keep gcc from complaining when we pass in volatile data. + * + * We should not need these routines, but the tcic controller will not work + * without them. This is probably a bug in the tcic controller, but for + * now it is much easier to fix here. You can probably turn this off if + * you are not using a tcic controller. + */ + #define USEVBCMP + + /* + * Pad all packets up to at least ETHER_MIN_LEN bytes. I am not sure + * this is actually needed. + */ + #define ETHER_MIN_LEN 64 + + #if 1 /* __FreeBSD__ */ + /* + * set 0x100 as a default domain when using access-points. + #define USE_ACCESSPOINTS + */ + #endif + + /* + * If cnw_debug is not 0, basic debugging statements are turned on. + * If the low nibble is > 1, more extensive debugging is turned on. + * If bit 0x10 is on in cnw_debug, interrupt debugging it turned on. + */ + int cnw_debug = 0; + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + + #ifdef INET + #include + #include + #include + #include + #include + #endif + #ifdef INET6 + #ifndef INET + #include + #endif + #include + #endif + + #include + #ifdef PC98 + #include + #else /*PC98*/ + #include + #endif /*PC98*/ + #if defined(__bsdi__) + #include + #elif defined(__FreeBSD__) + #include + #endif + + #include "bpfilter.h" + #if NBPFILTER > 0 + #include + #include + #endif /*NBPFILTER*/ + + #include + #include + #if defined(__FreeBSD__) + #include + #include + #include + #include + #include + #endif + + #if defined(__bsdi__) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + #include "if_cnwreg.h" + #include "if_cnwioctl.h" + + #elif defined(__FreeBSD__) + #include "card.h" + #include + #include + #include + #include + + #include + + #include + #include + + #endif /* __FreeBSD__ */ + + #ifdef USEVBCMP + #define bcmp vbcmp + #define bcopy vbcopy + static int vbcmp(char volatile *, char volatile *, int); + static void vbcopy(char volatile *, char volatile *, int); + #endif + + #if defined(__FreeBSD__) + #define MULTICAST + #define IFF_NOTRAILERS 0 + #define ETHER_IS_MULTICAST(x) ((*(u_char *)x) & 0x01) + #endif + + struct nw_softc { + struct device nw_dev; /* base device (must be first) */ + #define nw_unit nw_dev.dv_unit + #if defined(__bsdi__) + struct isadev nw_id; /* ISA device */ + struct intrhand nw_ih; /* interrupt vectoring */ + #elif defined(__FreeBSD__) + struct pccard_devinfo *nw_devi; /* pccard device */ + #endif + struct arpcom nw_ac; /* Ethernet common part */ + #define nw_if nw_ac.ac_if /* network-visible interface */ + #define nw_addr nw_ac.ac_enaddr /* hardware Ethernet address */ + + int nw_ifoflags; + + caddr_t nw_mbase; /* shared memory base */ + int nw_base; /* io port base address */ + int nw_psize; /* number of io ports */ + volatile struct nwreg *nw_reg; /* memory buffer */ + volatile struct nwcreg *nw_creg;/* control registers */ + + u_short nw_domain; /* current active NetWave domain */ + u_short nw_skey; /* current scramble key */ + struct cnwstats nw_stats; + + #if defined(__bsdi__) + CliHandle_t nw_clihdl; + #endif + int nw_socket; + #if defined(__bsdi__) + cs_rio_t nw_rio; + cs_rirq_t nw_rirq; + cs_cfg_t nw_rcfg; + WinHandle_t nw_winhdl; + #endif + int nw_irq; /* interrupt vectoring */ + u_short nw_txready; /* Number of bytes ready to xmit */ + short nw_configured:1; + short nw_detaching:1; + short nw_active:1; /* Currently xmitting a packet */ + struct timeval nw_txlast; /* time of last packet sent */ + }; + + int cnwprobe (struct device *, struct cfdata *, void *); + void cnwattach (struct device *, struct device *, void *); + int cnwintr (struct nw_softc *); + #if defined(__bsdi__) + int cnwstart (struct ifnet *); + int cnwioctl (struct ifnet *, u_long, caddr_t); + int cnw_cse_handler(); + #elif defined(__FreeBSD__) + void cnwstart (struct ifnet *); + int cnwioctl (struct ifnet *, int, caddr_t); + #endif + + #if defined(__FreeBSD__) + #define DV_NET DV_IFNET + #endif + struct cfdriver cnwcd = + { NULL, "cnw", cnwprobe, cnwattach, DV_NET, sizeof(struct nw_softc) }; + + static int cnwmax; + + #if defined(__bsdi__) + static int cnw_cc_probe(); + static int cnw_cc_attach(); + static int cnw_cc_detach(); + #elif defined(__FreeBSD__) + static int cnw_cc_probe(struct nw_softc *, int); + static int cnw_cc_attach(struct nw_softc *, int); + static int cnw_cc_detach(struct nw_softc *, int); + #endif + + static int cnw_cmd(struct nw_softc *, ...); + static int cnw_cwait (volatile struct nwcreg *); + static int cnw_init (int); + #if defined(__FreeBSD__) + static void cnw_ifinit (void *); + #endif + static int cnw_reset(struct nw_softc *); + static int cnw_setdomain(struct nw_softc *, int); + static int cnw_setkey(struct nw_softc *, int); + static void cnw_recv (struct nw_softc *); + + static void _cnwprintf(struct nw_softc *, char *, ...); + + static int mcopy_out (struct nw_softc *, struct mbuf *); + static struct mbuf *mcopy_in (struct nw_softc *); + + /* + * Wait for last command to complete + */ + static int wccline = 0; + #define WCC(nwc) ((wccline = __LINE__), !((nwc)->nwc_isr & (NWR_READY)) ? cnw_cwait(nwc) : 0) + + /* + * Offsets into memory areas + */ + #define nwreg_off(x) ((int)&((struct nwreg *)0)->x) + #define nwcreg_off(x) ((int)&((struct nwcreg *)0)->x) + + /* + * Debug printfs + */ + #define cnwprintf if (cnw_debug) _cnwprintf + #define cnwprintf2 if ((cnw_debug & 0x0f) >= 2) _cnwprintf + #define icnwprintf if (cnw_debug & 0x10) _cnwprintf + + #ifdef CNW_TRAIL + static struct cnwtrail trail[128]; + static int head = 0; + static int lastsent = 0; + #endif + + #if defined(__FreeBSD__) + + /* + * PC-Card (PCMCIA) specific code. + */ + static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ + static void cnwunload(struct pccard_devinfo *); /* Disable driver */ + static int cnwcrdinit(struct pccard_devinfo *); /* init device */ + + static struct pccard_device cnw_info = { + "cnw", + cnwcrdinit, + cnwunload, + card_intr, + 0, /* Attributes - presently unused */ + &net_imask /* Interrupt mask for device */ + }; + + struct nw_softc *cnw_scs[NCNW]; + + /* + * Initialize the device - called from Slot manager. + */ + static int + cnwcrdinit(struct pccard_devinfo *devi) + { + struct nw_softc *nw; + int sock, unit; + + unit = devi->pd_unit; + + /* validate unit number. */ + if (devi->pd_unit >= NCNW) + return(ENODEV); + + if ((nw = cnw_scs[devi->pd_unit]) == NULL) { + /* first time */ + MALLOC(nw, struct nw_softc *, sizeof(struct nw_softc), + M_DEVBUF, M_WAITOK); + if (nw == NULL) + return(ENOBUFS); + + bzero(nw, sizeof(struct nw_softc)); + + /* fake a cfdriver structure */ + cnwcd.cd_devs = (void **)cnw_scs; + cnwcd.cd_devs[unit] = nw; + cnwcd.cd_ndevs = NCNW; + /* fake a device structure in nw_softc */ + nw->nw_dev.dv_unit = unit; + sprintf(nw->nw_dev.dv_xname, "cnw%d", unit); + nw->nw_if.if_snd.ifq_maxlen = ifqmaxlen; /* XXX */ + nw->nw_devi = devi; /* pccard_dev */ + + cnwattach(NULL, (struct device *)nw, NULL); + } + else { + /* card is reinserted! we don't free nw_softc when + * the card is ejected since freeing if (which is + * in the nw_softc) is problematic. + */ + nw->nw_devi = devi; /* don't forget to update pccard_dev */ + } + + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + nw->nw_socket = -1; + #if 1 + sock = 0; + #else + sock = devi->sp->slot; /* really? */ + #endif + if (cnw_cc_probe(nw, sock)) { + if (cnw_cc_attach(nw, sock) == 0) { + printf("cnw%d: attach failed!\n", unit); + return (ENXIO); + } + #ifdef INET6 + in6_ifattach(&nw->nw_if, IN6_IFT_802, (caddr_t)nw->nw_addr, 0); + #endif /* INET6 */ + } + return(0); + } + + /* + * cnwunload - unload the driver and clear the table. + * XXX TODO: + * This is usually called when the card is ejected, but + * can be caused by a modunload of a controller driver. + * The idea is to reset the driver's view of the device + * and ensure that any driver entry points such as + * read and write do not hang. + */ + static void + cnwunload(struct pccard_devinfo *devi) + { + struct nw_softc *nw = cnwcd.cd_devs[devi->pd_unit]; + struct ifnet *ifp = &nw->nw_if; + + ifp->if_flags &= ~IFF_RUNNING; + if_down(ifp); + nw->nw_socket = -1; + printf("cnw%d: unload\n", devi->pd_unit); + } + + /* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int + card_intr(struct pccard_devinfo *devi) + { + struct nw_softc *nw = cnwcd.cd_devs[devi->pd_unit]; + + cnwintr(nw); + return(1); + } + + int cnw_isa_probe(struct isa_device *); + static int cnw_isa_attach(struct isa_device *is); + + struct isa_driver cnwdriver = { + cnw_isa_probe, + cnw_isa_attach, + "cnw", + 0 + }; + + int + cnw_isa_probe(id) + struct isa_device *id; + { + /* + * If PC-Card probe required, then register driver with + * slot manager. + */ + pccard_add_driver(&cnw_info); + return 0; + } + + /* never called */ + static int + cnw_isa_attach(id) + struct isa_device *id; + { + printf("cnw: isa_attach!! shouldn't be called\n"); + return 1; + } + + #endif /* __FreeBSD__ */ + + /* ARGSUSED */ + int + cnwprobe(struct device *parent, struct cfdata *cf, void *aux) + { + #if defined(__bsdi__) + register struct isa_attach_args *ia = (struct isa_attach_args *) aux; + + ia->ia_irq = IRQNONE; + #ifdef DIAGNOSTIC + if (sizeof(struct nwreg) != 0x1A0) { + printf("cnw: %d != 0x1A0\n", sizeof(struct nwreg)); + return (0); + } + #endif + #elif defined(__FreeBSD__) + /* never happnes */ + #endif /* __FreeBSD__ */ + return (1); + } + + /* + * cnwattach: this is a dummy routine that make the system think + * there's an interface. Make the interface (virtually) visilble + * by filling in the network interface record. Also register with + * socket driver to inform us in the event of card insertion. + */ + /* ARGSUSED */ + void + cnwattach(struct device *parent, struct device *self, void *aux) + { + register struct nw_softc *nw = (struct nw_softc *) self; + int unit = nw->nw_unit; + register struct ifnet *ifp = &nw->nw_if; + #if defined(__bsdi__) + cs_rclient_t rcli; + #endif + + /* + * Initialize local variables + */ + nw->nw_mbase = NULL; + #ifndef USE_ACCESSPOINTS + nw->nw_domain = NW_DOMAIN; + #else + nw->nw_domain = NW_ACCESSPOINT; /* default to use access-points */ + #endif + nw->nw_skey = 0; + + cnwmax = max(unit, cnwmax); + + /* + * Initialize interface structure + */ + ifp->if_unit = unit; + ifp->if_name = cnwcd.cd_name; + /* + * Our MTU could be much larger, but ether_attach will set it + * to ETHERMTU as well. + * An MTU of 3000 has shown up to a 5% improvement in speed, + * that is only between machines on the local netwave net. + */ + ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | + IFF_NOTRAILERS; + #if defined(__bsdi__) + ifp->if_init = cnw_init; + #elif defined(__FreeBSD__) + ifp->if_init = cnw_ifinit; + #endif + ifp->if_start = cnwstart; + ifp->if_ioctl = cnwioctl; + ifp->if_watchdog = 0; + #if defined(__bsdi__) + ether_attach(ifp); + #elif defined(__FreeBSD__) + ifp->if_output = ether_output; + ifp->if_softc = nw; + if_attach(ifp); + ether_ifattach(ifp); + #endif + ifp->if_baudrate = 1*1000*1000; /* Default, drivers may update */ + #ifndef USE_ACCESSPOINTS + ifp->if_mtu = 3000; /* We can do better than 1500 */ + #endif + + #if NBPFILTER > 0 + #if defined(__bsdi__) + bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); + #elif defined(__FreeBSD__) + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); + #endif + #endif /*NBPFILTER*/ + + bzero(nw->nw_addr, sizeof(nw->nw_addr)); + nw->nw_irq = 0; + nw->nw_reg = 0; + nw->nw_configured = 0; + nw->nw_socket = -1; + nw->nw_detaching = 0; + + #if defined(__bsdi__) + nw->nw_ih.ih_fun = cnwintr; + nw->nw_ih.ih_arg = (void *)nw; + + /* + * Initialize card client structure + */ + rcli.Attributes = CSCLI_IO; + rcli.EventMask = ~CSEM_CD_CHANGE; + rcli.CallBack = cnw_cse_handler; + rcli.CallBackArg = nw; + cs_RegisterClient(&nw->nw_clihdl, &rcli); + + isa_establish(&nw->nw_id, &nw->nw_dev); + + printf(": PCCARD Netwave AirSurfer\n"); + #elif defined(__FreeBSD__) + printf("cnw%d: PCCARD Netwave AirSurfer: domain set to 0x%x\n", + unit, nw->nw_domain); + #endif /* __FreeBSD__ */ + } + + /* + * Handle a pending interrupt. Keep looping until all interrupts + * are handled. + */ + int + cnwintr(register struct nw_softc *nw) + { + register volatile struct nwreg *nwr = nw->nw_reg; + register volatile struct nwcreg *nwc = nw->nw_creg; + register u_char isr, stat; + register struct ifnet *ifp = &nw->nw_if; + + if (nw->nw_detaching) + return (1); + + if (nw->nw_socket < 0) { + printf("cnwintr: stale\n"); + return (0); + } + + nwc->nwc_ictrl = NWR_IDISABLE; + + again: + if (WCC(nwc)) goto wedged; + + if (!(nwc->nwc_ccsr & NWR_IREADY)) { + icnwprintf(nw, "no interrupt ready\n"); + nwc->nwc_ictrl = NWR_IENABLE; + return (1); + } + + isr = nwc->nwc_isr; + + icnwprintf(nw, "isr 0x%x\n", isr); + + if ((isr & (NWR_RXAVAIL|NWR_RXERR|NWR_TXSTAT)) == 0) { + icnwprintf(nw, "empty interrupt\n"); + nwc->nwc_ictrl = NWR_IENABLE; + return (1); + } + + /* + * The linux driver actually picks up multiple packets at this + * point, looking at nwc->nwc_isr after each packet to see if + * the NWR_RXAVAIL bit has been turned off. + */ + if (isr & NWR_RXAVAIL) { + nw->nw_stats.nws_rx++; + cnw_recv(nw); + } + + if (isr & NWR_RXERR) { + nw->nw_stats.nws_rxerr++; + if (WCC(nwc)) goto wedged; + nwr->nwr_runstate = NWR_HALT; + + if (WCC(nwc)) goto wedged; + + stat = nwr->nwr_rstat; + + icnwprintf(nw, "rstat 0x%x\n", stat); + + if (stat & NWR_RSTAT_OVERFLOW) { + /* + * RX overflow detected. Disable receiver and + * process all pending packets before going on. + */ + nw->nw_stats.nws_rxoverflow++; + icnwprintf(nw, "overflow, rbuffer 0x%x\n", + nwr->nwr_rbuffer); + + /* Disable receiver */ + if (cnw_cmd(nw, NW_CMD_SET_RXMODE, 0, -1)) + goto wedged; + + cnw_recv(nw); + + nwr->nwr_rclr = NWR_RSTAT_RXERROR | + (stat & (NWR_RSTAT_CRCERR|NWR_RSTAT_FRAME)); + + /* Re-enable receiver */ + if (cnw_cmd(nw, NW_CMD_SET_RXMODE, NW_RXMODE(nw), -1)) + goto wedged; + } + + if (stat & NWR_RSTAT_OVERRUN) { + /* + * RX overrun. Not much we can do here except for + * blaming slow 80188. + */ + nw->nw_stats.nws_rxoverrun++; + } + + if (stat & NWR_RSTAT_CRCERR) { + /* + * RX crc error. Look for microwave ovens near by. + */ + nw->nw_stats.nws_rxcrcerror++; + } + + if (stat & NWR_RSTAT_FRAME) { + /* + * received a framing error + */ + nw->nw_stats.nws_rxframe++; + } + + if (stat & NWR_RSTAT_RXERROR) { + /* + * Generic RX error + */ + nw->nw_stats.nws_rxerrors++; + } + + if (stat & NWR_RSTAT_RXAVAIL) { + /* + * There is a buffer available + */ + nw->nw_stats.nws_rxavail++; + } + + if (stat & 1) { + /* + * This bit is unused? Keep track of it anyhow. + */ + nw->nw_stats.nws_rxone++; + } + + nwr->nwr_rclr = NWR_RSTAT_RXERROR | + (stat & (NWR_RSTAT_CRCERR|NWR_RSTAT_FRAME)); + + } + + if (isr & NWR_TXSTAT) { + #ifdef ONE_AT_A_TIME + /* + * Any response to a transmit means the current + * packet is done + */ + nw->nw_active = 0; + #endif + /* + * TX status change interrupt. + */ + + if (WCC(nwc)) goto wedged; + stat = nwr->nwr_tstat; + + icnwprintf(nw, "tstat 0x%x\n", stat); + #ifdef CNW_TRAIL + microtime(&trail[lastsent].done); + trail[lastsent].status = stat; + #endif + + if (stat & NWR_TSTAT_OKAY) { + /* + * Transmission complete without error. + */ + nw->nw_stats.nws_txokay++; + nw->nw_stats.nws_txretries[stat & 0xf]++; + + ifp->if_opackets++; + ifp->if_collisions += stat & 0xf; + icnwprintf(nw, "Packet was sent!\n"); + + if (WCC(nwc)) goto wedged; + nwr->nwr_tclr = NWR_TSTAT_OKAY | 0xf; + } + + if (stat & NWR_TSTAT_ABORT) { + /* + * TX giveup: Happens if destination is not + * within the reach when unicast is attempted + * in peer-to-peer mode. Note that broadcast + * packets does not cause this error. + */ + nw->nw_stats.nws_txabort++; + icnwprintf(nw, "transmit error\n"); + } + + if (stat & NWR_TSTAT_CARRLOST) { + /* + * TX carrier lost: Happens if AP is not + * responding when operating in the server- + * client mode. Note that both unitcast and + * broadcast packets cause this error, since + * all packets are initially destined for + * AP first. + */ + nw->nw_stats.nws_txlostcd++; + icnwprintf(nw, "transmit carrier lost\n"); + } + if (stat & NWR_TSTAT_TERR) { + nw->nw_stats.nws_txerrors++; + icnwprintf(nw, "transmit error\n"); + } + if (stat & (NWR_TSTAT_ABORT|NWR_TSTAT_CARRLOST|NWR_TSTAT_TERR)){ + if (WCC(nwc)) goto wedged; + nwr->nwr_tclr = NWR_TSTAT_ABORT | NWR_TSTAT_CARRLOST | + NWR_TSTAT_TERR | 0xf; + ifp->if_oerrors++; + } + if (WCC(nwc)) goto wedged; + + ifp->if_flags &= ~IFF_OACTIVE; + + if (nw->nw_txready || ifp->if_snd.ifq_len) + cnwstart(ifp); + } + + goto again; + + if (0) { + wedged: cnwprintf(nw, "controller wedged @ %d\n", wccline); + } + nwc->nwc_ictrl = NWR_IENABLE; + return (1); + } + + /* + * Send out any packets that have already been loaded into the card but + * not yet sent. Then, start pulling mbufs of the chain and stuffing + * them into the card. Stop when we find that the previous packet we + * stuffed in was not sent or when we run out of mbufs. + */ + #if defined(__bsdi__) + int + #elif defined(__FreeBSD__) + void + #endif + cnwstart(struct ifnet *ifp) + { + struct nw_softc *nw = cnwcd.cd_devs[ifp->if_unit]; + register volatile struct nwreg *nwr = nw->nw_reg; + register volatile struct nwcreg *nwc = nw->nw_creg; + struct mbuf *m0; + struct timeval now; + + #ifdef DIAGNOSTIC + if (nw->nw_if.if_flags & IFF_OACTIVE) + printf("cnw%d: cnwstart reentered", nw->nw_unit); + #endif + for (;;) { + microtime(&now); + now.tv_sec -= nw->nw_txlast.tv_sec; + now.tv_usec -= nw->nw_txlast.tv_usec; + if (now.tv_usec < 0) { + now.tv_usec += 1000000; + now.tv_sec -= 1; + } + if (nw->nw_txready) { + #ifdef ONE_AT_A_TIME + /* + * Don't ship this packet out until the last + * packet has left the building. + * If we have not tried to send a packet for 1/5 + * a second then we assume we lost an interrupt, + * lets go on and send the next packet anyhow. + * + * I suppose we could check to see if it is okay + * to put additional packets on the card (beyond + * the one already waiting to be sent) but I don't + * think we would get any improvement in speed as + * we should have ample time to put the next packet + * on while this one is going out. + */ + if (nw->nw_active && + now.tv_sec == 0 && now.tv_usec < 200000) + goto out; + #endif + #ifdef ETHER_MIN_LEN + if (nw->nw_txready < ETHER_MIN_LEN) + nw->nw_txready = ETHER_MIN_LEN; + #endif + + cnwprintf(nw, "sending packet of %d bytes\n", + nw->nw_txready); + nw->nw_stats.nws_tx++; + microtime(&nw->nw_txlast); + #ifdef CNW_TRAIL + trail[head].what = NW_CMD_TX_START; + trail[head].status = 0; + trail[head].length = nw->nw_txready; + trail[head].when = nw->nw_txlast; + lastsent = head; + if (++head == 128) + head = 0; + #endif + if (cnw_cmd(nw,NW_CMD_TX_START,SA(nw->nw_txready),-1)) { + nw->nw_txready = 0; + goto out; + } + nw->nw_txready = 0; + #ifdef ONE_AT_A_TIME + nw->nw_active = 1; + #endif + } + + /* + * Make sure the link integrity field is on + */ + if (WCC(nwc)) goto wedged; + + if (nwr->nwr_lif == 0) { + nw->nw_if.if_flags &= ~IFF_OACTIVE; + #if defined(__bsdi__) + return (ENETDOWN); + #elif defined(__FreeBSD__) + return; + #endif + } + + /* + * Make sure the transmit buffer is available + */ + if (WCC(nwc)) goto wedged; + + if ((nwc->nwc_isr & NWR_TXEMP) == 0) { + cnwprintf(nw, "no empty buffers\n"); + goto out; + } + + if (WCC(nwc)) goto wedged; + + IF_DEQUEUE(&nw->nw_if.if_snd, m0); + + if (m0 == 0) { + cnwprintf(nw, "no more mbufs\n"); + goto out; + } + + nw->nw_if.if_flags |= IFF_OACTIVE; + + /* + * Feed outgoing packet to bpf + */ + #if NBPFILTER > 0 + #if defined(__bsdi__) + if (nw->nw_if.if_bpf) + bpf_mtap(nw->nw_if.if_bpf, m0); + #elif defined(__FreeBSD__) + if (nw->nw_if.if_bpf) + bpf_mtap(&nw->nw_if, m0); + #endif + #endif /*NBPFILTER*/ + + nw->nw_txready = mcopy_out(nw, m0); + } + out: + if (0) { + wedged: cnwprintf(nw, "controller wedged @ %d\n", wccline); + } + nw->nw_if.if_flags &= ~IFF_OACTIVE; + #if defined(__bsdi__) + return (0); + #endif + } + + /* + * Process an ioctl request. + */ + int + #if defined(__bsdi__) + cnwioctl(struct ifnet *ifp, u_long cmd, caddr_t data) + #elif defined(__FreeBSD__) + cnwioctl(struct ifnet *ifp, int cmd, caddr_t data) + #endif + { + register struct ifaddr *ifa = (struct ifaddr *)data; + struct nw_softc *nw = (struct nw_softc *) cnwcd.cd_devs[ifp->if_unit]; + int s; + int error = 0; + struct proc *p = curproc; + + s = splimp(); + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + + switch (ifa->ifa_addr->sa_family) { + #ifdef INET + case AF_INET: + cnw_init(ifp->if_unit); + arp_ifinit((struct arpcom *)ifp, ifa); + break; + #endif + #ifdef INET6 + case AF_INET6: + cnw_init(ifp->if_unit); + break; + #endif + default: + cnw_init(ifp->if_unit); + break; + } + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + ifp->if_flags & IFF_RUNNING) { + ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); + #if defined(__FreeBSD__) + /* if is down, stop the card. */ + cnw_reset(nw); + #endif + } else + cnw_init(ifp->if_unit); + break; + + #ifdef SIOCSIFMTU + case SIOCSIFMTU: + /* + * set the interface MTU. it is ok to set a larger MTU + * than Ethernet. + */ + ifp->if_mtu = ((struct ifreq *)data)->ifr_mtu; + break; + #endif + + #ifdef MULTICAST + /* + * Update our multicast list. + */ + case SIOCADDMULTI: + error = ether_addmulti((struct ifreq *)data, &nw->nw_ac); + goto reset; + + case SIOCDELMULTI: + error = ether_delmulti((struct ifreq *)data, &nw->nw_ac); + reset: + if (error == ENETRESET) { + cnw_init(ifp->if_unit); + error = 0; + } + break; + #endif + #ifdef notdef + case SIOCGHWADDR: + bcopy(nw->nw_addr, &ifr->ifr_data, sizeof(nw->nw_addr)); + break; + #endif + case SIOCGIFADDR: + bcopy(nw->nw_addr, ((struct ifreq *)data)->ifr_addr.sa_data, + sizeof(nw->nw_addr)); + break; + case SIOCGCNWDOMAIN: + ((struct ifreq *)data)->ifr_domain = nw->nw_domain; + break; + case SIOCSCNWDOMAIN: + if ((error = suser(p->p_ucred, &p->p_acflag)) == 0) + error = cnw_setdomain(nw, + ((struct ifreq *)data)->ifr_domain); + #if 1 /* __FreeBSD__ */ + if (error == 0) { + /* + * reset MTU. 1500 bytes when using access-points, + * 3000 bytes when peer-to-peer. + */ + if (nw->nw_domain & 0x100) + ifp->if_mtu = ETHERMTU; + else + ifp->if_mtu = 3000; + } + #endif + break; + case SIOCSCNWKEY: + if ((error = suser(p->p_ucred, &p->p_acflag)) == 0) + error = cnw_setkey(nw, + ((struct ifreq *)data)->ifr_key); + break; + case SIOCGCNWSTATUS: + if ((error = suser(p->p_ucred, &p->p_acflag)) == 0 && + ifp->if_flags & IFF_RUNNING) + bcopy((void *)nw->nw_reg->nwr_cmd, + ((struct cnwstatus *)data)->data, 0x100); + break; + case SIOCGCNWSTATS: + bcopy((void *)&nw->nw_stats, + (void *)&(((struct cnwistats *)data)->stats), + sizeof(struct cnwstats)); + break; + #ifdef CNW_TRAIL + case SIOCGCNWTRAIL: + bcopy((void *)&trail, (void *)((struct cnwitrail *)data)->trail, + sizeof(struct cnwitrail)); + ((struct cnwitrail *)data)->head = head; + break; + #endif + default: + error = EINVAL; + } + nw->nw_ifoflags = ifp->if_flags; + splx(s); + return (error); + } + + #if defined(__bsdi__) + /* + * Callback interface: + * Handler(CliData, Function, Socket, Info, MTDRequest, Buffer, Misc, Status) + * + * Function: event/function. + * Socket: socket affected by the event. + * Info: contains other information specific to the event. + * MTDRequest: + * Buffer: + * Misc: + */ + struct mtdreq; /* we never use it, but this makes gcc2 shut up */ + + int + cnw_cse_handler(void *clidata, int func, int sock, int info, + struct mtdreq *mtdreq, char *buf, int misc) + { + struct nw_softc *nw = (struct nw_softc *)clidata; + + switch(func) { + case CSE_CARD_INSERTION: + if (cu_configured(&nw->nw_clihdl, sock) || nw->nw_socket >= 0) + break; + + if (cnw_cc_probe(nw, sock)) + cnw_cc_attach(nw, sock); + break; + + case CSE_CARD_REMOVAL: + cnw_cc_detach(nw, sock); + break; + + case CSE_CLIENT_INFO: + break; + + default: + break; + } + return (0); + } + #endif /* __bsdi__ */ + + /* + * Probe routine called upon the card insertion event. + */ + static int + cnw_cc_probe(struct nw_softc *nw, int socket) + { + u_char addr[6]; + int err, j; + struct nw_softc *no; + + #if defined(__bsdi__) + cs_rmem_t rmem; + cs_rmemrw_t rmemrw; + MemHandle_t mh; + + if (cs_spec_lookup(socket, "cnw", NULL, 0)) { + cnwprintf(nw, "cnw_cc_probe: no match\n"); + return (0); + } + + rmem.Socket = socket; + rmem.Attributes = 0; + rmem.Offset = 0; + + if ((err = cs_OpenMemory(&nw->nw_clihdl, &mh, &rmem)) != 0) { + cnwprintf(nw, "OpenMemory err 0x%x\n", err); + return (0); + } + + rmemrw.CardOffset = NW_MEM_ADDR + nwreg_off(nwr_addr); + rmemrw.Count = sizeof(addr); + + err = cs_ReadMemory(&nw->nw_clihdl, &mh, addr, &rmemrw); + + cs_CloseMemory(&nw->nw_clihdl, &mh); + + if (err) { + cnwprintf(nw, "ReadMemory err 0x%x\n", err); + return (0); + } + cnwprintf(nw, "ether address of %s\n", ether_sprintf(addr)); + + /* + * First, check out if this card has been handled by other units. + * But before doing that, we scan other units to see + * if the card has been accepted by is one of them. + */ + + for (j = 0; j < cnwmax; j++) { + if (j == nw->nw_unit) + continue; /* This is me */ + no = cnwcd.cd_devs[j]; + if (bcmp(no->nw_addr, addr, 6) == 0) { + cnwprintf(nw, "card handled by cnw%d\n", j); + return (0); + } + } + + if (nw->nw_addr[0] == 0 && nw->nw_addr[1] == 0 + && nw->nw_addr[2] == 0 && nw->nw_addr[3] == 0 + && nw->nw_addr[4] == 0 && nw->nw_addr[5] == 0) { + register struct ifnet *ifp = &nw->nw_if; + register struct ifaddr *ifa; + register struct sockaddr_dl *sdl; + /* + * This client is fresh. Can accept a new card. + */ + bcopy(addr, (void *)nw->nw_addr, sizeof(nw->nw_addr)); + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { + if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && + sdl->sdl_family == AF_LINK) { + bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr + , + LLADDR(sdl), ifp->if_addrlen); + break; + } + } + cnwprintf(nw, "first card inserted\n"); + return (1); + } + + /* + * This client has accepted a card before. + * Check out if the card is the one we've seen before. + */ + if (bcmp(addr, nw->nw_addr, sizeof(nw->nw_addr)) == 0) { + cnwprintf(nw, "same card re-inserted\n"); + return (1); + } + + cnwprintf(nw, "different card inserted (rejected)\n"); + return (0); + #elif defined(__FreeBSD__) + struct pccard_devinfo *devi = nw->nw_devi; + int i; + + /* ethernet address is passed from pccardd */ + for (i = 0; i < ETHER_ADDR_LEN; ++i) + addr[i] = devi->misc[i]; + + cnwprintf(nw, "ether address of %6D\n", addr, ":"); + + if (*(int *)addr == 0) { + printf("ether address invalid!\n"); + return 0; + } + + /* + * FreeBSD reuses unit numbers + */ + /* + * Check out if the card is the one we've seen before. + */ + if (bcmp(addr, nw->nw_addr, sizeof(nw->nw_addr)) == 0) { + cnwprintf(nw, "same card re-inserted\n"); + return (1); + } + + do { + register struct ifnet *ifp = &nw->nw_if; + register struct ifaddr *ifa; + register struct sockaddr_dl *sdl; + + bcopy(addr, (void *)nw->nw_addr, sizeof(nw->nw_addr)); + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { + if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && + sdl->sdl_family == AF_LINK) { + bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, + LLADDR(sdl), ifp->if_addrlen); + break; + } + } + if (nw->nw_addr[0] == 0 && nw->nw_addr[1] == 0 + && nw->nw_addr[2] == 0 && nw->nw_addr[3] == 0 + && nw->nw_addr[4] == 0 && nw->nw_addr[5] == 0) + cnwprintf(nw, "first card inserted\n"); + else + cnwprintf(nw, "different card inserted\n"); + + return (1); + } while (0); + return (0); + #endif /* __FreeBSD__ */ + } + + /* + * Attach it. It would be be nice if we could look at the CIS and determine + * how to program the card, but some cards contain A WHOLE LOTS OF GARBAGE + * in the CIS including several big lies, such as the CISTPL_CONF that's + * trying to pretend it is a plain memory card as well as an incorrect VPP + * specification, so we will presume the following configuration: + * + * Power: 5V to Vcc, 0V to Vpp1 and Vpp2. + * I/O Ports: either 16 or none required (currently we use memory mapping) + * IRQ: One required. + * Window: Common memory, card offset 0x20000-0x28fff for controller + * command and buffer access. No wait state (Assume 400nsec). + * COR: At 0x200 + * COR value: 0x41 (0x01) + * Other regs: CCSR + */ + + static int + cnw_cc_attach(struct nw_softc *nw, int socket) + { + int unit = nw->nw_dev.dv_unit; + #if defined(__bsdi__) + cs_rwin_t rwin; + cs_rpage_t rpage; + #endif + int err; + + nw->nw_socket = socket; + + #if defined(__bsdi__) + /* + * Start out with allocating IRQ + */ + nw->nw_rirq.Socket = socket; + nw->nw_rirq.Attributes = 0; + nw->nw_rirq.IRQInfo1 = CSIRQ_LEVEL|CSIRQ_MASKS; + nw->nw_rirq.IRQInfo2 = 0xffff; + + err = cs_RequestIRQ(&nw->nw_clihdl, &nw->nw_rirq); + + if (err) { + printf("cnw%d: RequestIRQ err 0x%x\n", unit, err); + goto bad; + } + + nw->nw_irq = irq_indextomask(nw->nw_rirq.AssignedIRQ); + dyna_intr_establish(nw->nw_irq, &nw->nw_ih, DV_NET); + + nw->nw_rcfg.cscfg_Socket = socket; + nw->nw_rcfg.cscfg_Attributes = 2; /* Enable IRQ */ + nw->nw_rcfg.cscfg_Vcc = 50; /* 5V to Vcc */ + nw->nw_rcfg.cscfg_Vpp1 = 0; + nw->nw_rcfg.cscfg_Vpp2 = 0; /* Vpp1 = Vpp2 = 0 */ + nw->nw_rcfg.cscfg_IntType = 2; /* I/O card */ + nw->nw_rcfg.cscfg_Present = CREGMAP_COR; + nw->nw_rcfg.cscfg_ConfigBase = 0x200; /* tpcc.tpcc_radr */ + nw->nw_rcfg.cscfg_ConfigIndex = 0x41; + + if ((err = cs_RequestConfiguration(&nw->nw_clihdl, &nw->nw_rcfg)) != 0){ + printf("cnw%d: RequestConfiguration err 0x%x\n", unit, err); + goto bad; + } + #endif + + nw->nw_configured = 1; + + #if defined(__bsdi__) + /* + * Things are going okay. Memory stuff next. + */ + rwin.Socket = socket; + rwin.Attributes = CSRWIN_ENABLE; + rwin.Base = 0; /* Pick available address */ + rwin.Size = 0x9000; /* Map 36KB (32K window + 4K register */ + rwin.AccessSpeed = (9<<3) | 2; /* 400 nsec */ + rwin.AccessSpeed = 1; /* XXX */ + if ((err = cs_RequestWindow(&nw->nw_clihdl, &nw->nw_winhdl, &rwin))!=0){ + printf("cnw%d: can't alloc win err 0x%x\n", unit, err); + goto bad; + } + + rpage.CardOffset = 0x20000; + rpage.Page = 0; + if ((err = cs_MapMemPage(&nw->nw_clihdl, &nw->nw_winhdl,&rpage)) != 0) { + printf("cnw%d: can't map win(comm) err 0x%x\n", unit, err); + goto bad; + } + + nw->nw_mbase = (caddr_t)cs_ptokvm(rwin.Base); + nw->nw_reg = (struct nwreg *)nw->nw_mbase; + nw->nw_creg = (struct nwcreg *)(nw->nw_mbase + NW_REG_ADDR-NW_MEM_ADDR); + cnwprintf(nw, "memory 0x%x(0x%x,0x%x)", rwin.Base, + nw->nw_reg, nw->nw_creg); + #elif defined(__FreeBSD__) + if (nw->nw_devi->pd_msize < 0x9000) { + printf("allocated memory too small!! size=0x%x need=0x%x\n", + nw->nw_devi->pd_msize, 0x9000); + goto bad; + } + nw->nw_mbase = nw->nw_devi->pd_maddr; + nw->nw_reg = (struct nwreg *)nw->nw_mbase; + nw->nw_creg = (struct nwcreg *)(nw->nw_mbase + NW_REG_ADDR-NW_MEM_ADDR); + cnwprintf(nw, "memory 0x%x(0x%x,0x%x)\n", nw->nw_mbase, + nw->nw_reg, nw->nw_creg); + #endif /* __FreeBSD__ */ + + /* + * Initialize + */ + if (cnw_reset(nw)) + goto bad; + + /* + * Sanity check CS/SS. If mapping has been done without trouble + * we should be able to read the mac address from nwr_addr + * (offset 0x160). If not, it's a botched assertion, and who knows. + */ + if (bcmp(nw->nw_addr, (void *)nw->nw_reg->nwr_addr, + sizeof(nw->nw_addr))) { + printf("cnw%d: sanity check failed on memory access\n", unit); + #if defined(__bsdi__) + cnwprintf(nw, "%s != ", ether_sprintf(nw->nw_addr)); + cnwprintf(NULL, "%s\n", + ether_sprintf((u_char *)nw->nw_reg->nwr_addr)); + #elif defined(__FreeBSD__) + printf("%6D != ", nw->nw_addr, ":"); + printf("%6D\n", nw->nw_reg->nwr_addr, ":"); + #endif + goto bad; + } + + cnwprintf(nw, "ID \"%c%c\" revision %04x %04x\n", + nw->nw_reg->nwr_id[0], nw->nw_reg->nwr_id[1], + nw->nw_reg->nwr_rev[0], nw->nw_reg->nwr_rev[1]); + + #if defined(__FreeBSD__) + /* initialization is done at if-up, to save power consumption */ + nw->nw_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); + return (1); + #endif + + if (cnw_init(nw->nw_if.if_unit) == 0) { + cnwprintf(nw, "initialization failure\n"); + goto bad; + } + + if (WCC(nw->nw_creg)) goto bad; + + nw->nw_creg->nwc_enable = NWR_ENORMAL; + + if (cnw_cmd(nw, NW_CMD_RUN, -1)) + goto bad; + + if (WCC(nw->nw_creg)) goto bad; + + return (1); + + bad: + cnw_cc_detach(nw, socket); + return (0); + } + + /* + * Detach the card and free all of its resources + */ + static int + cnw_cc_detach(struct nw_softc *nw, int socket) + { + if (socket < 0 || nw->nw_socket != socket) + return (0); + + nw->nw_detaching = 1; + + nw->nw_if.if_flags &= ~IFF_RUNNING; + + if (nw->nw_reg) { + cnwprintf(nw, "releasing window\n"); + #if defined(__bsdi__) + cs_ReleaseWindow(&nw->nw_clihdl, &nw->nw_winhdl); + #endif + nw->nw_reg = 0; + } + + if (nw->nw_configured) { + cnwprintf(nw, "releasing configuration\n"); + #if defined(__bsdi__) + cs_ReleaseConfiguration(&nw->nw_clihdl, &nw->nw_rcfg); + #endif + nw->nw_configured = 0; + } + + if (nw->nw_base) { + cnwprintf(nw, "releasing io ports\n"); + #if defined(__bsdi__) + cs_ReleaseIO(&nw->nw_clihdl, &nw->nw_rio); + #endif + nw->nw_base = 0; + } + + if (nw->nw_irq) { + cnwprintf(nw, "releasing interrupt vector\n"); + #if defined(__bsdi__) + cs_ReleaseIRQ(&nw->nw_clihdl, &nw->nw_rirq); + + cnwprintf(nw, "releasing interrupt handler\n"); + dyna_intr_release(nw->nw_irq, &nw->nw_ih); + #endif + nw->nw_irq = 0; + } + + nw->nw_socket = -1; + nw->nw_detaching = 0; + cnwprintf(nw, "released\n"); + return (0); + } + + /* + * Initialize card + */ + #if defined(__FreeBSD__) + static void cnw_ifinit (sc) + void *sc; + { + struct nw_softc *nw = (struct nw_softc *)sc; + + cnw_init(nw->nw_unit); + } + #endif + static int + cnw_init(int unit) + { + register struct nw_softc *nw = cnwcd.cd_devs[unit]; + struct ifnet *ifp = &nw->nw_if; + int s; + register volatile struct nwcreg *nwc = nw->nw_creg; + + if (ifp->if_addrlist == (struct ifaddr *) 0) { + cnwprintf(nw, "no address list\n"); + return (0); + } + + if ((ifp->if_flags & IFF_RUNNING) && ifp->if_flags == nw->nw_ifoflags) { + cnwprintf(nw, "already running\n"); + return (0); + } + + if (nw->nw_socket < 0) { + cnwprintf(nw, "unit not currently inserted\n"); + return (0); + } + + s = splimp(); + + if (cnw_cmd(nw, NW_CMD_INIT, -1)) + goto wedged; + + /* + * RX mode + */ + if (cnw_cmd(nw, NW_CMD_SET_RXMODE, NW_RXMODE(nw), -1)) + goto wedged; + + /* + * TX mode + */ + if (cnw_cmd(nw, NW_CMD_SET_TXMODE, NW_TXENA, -1)) + goto wedged; + + /* + * Set domain (access point or add hoc) + */ + if (cnw_cmd(nw, NW_CMD_SET_DOMAIN, SA(nw->nw_domain), -1)) + goto wedged; + + /* + * Set Scramble Key + */ + if (cnw_cmd(nw, NW_CMD_SET_SKEY, SA(nw->nw_skey), -1)) + goto wedged; + + if (WCC(nwc)) goto wedged; + + nwc->nwc_ictrl = NWR_INORMAL; + + if (WCC(nwc)) goto wedged; + + #if defined(__FreeBSD__) + /* run command is added here to stop the card when if is down. */ + + nw->nw_creg->nwc_enable = NWR_ENORMAL; + + if (cnw_cmd(nw, NW_CMD_RUN, -1)) + goto wedged; + + if (WCC(nw->nw_creg)) goto wedged; + #endif /* __FreeBSD__ */ + + nw->nw_if.if_flags &= ~IFF_OACTIVE; + nw->nw_if.if_flags |= IFF_RUNNING; + + cnwstart(ifp); + splx(s); + return (1); + wedged: + splx(s); + cnwprintf(nw, "controller wedged @ %d\n", wccline); + return (0); + } + + /* + * do a hardware reset on the card + */ + static int + cnw_reset(struct nw_softc *nw) + { + int retry = 0; + + nw->nw_creg->nwc_reset = NWR_RESET; + nw->nw_reg->nwr_runstate = NWR_READY; + nw->nw_creg->nwc_reset = NWR_NOTRESET; + + while (!(nw->nw_creg->nwc_isr & NWR_READY)) { + if (++retry > 1000) { + nw->nw_creg->nwc_reset = NWR_RESET; + cnwprintf(nw, "hardware reset failed\n"); + return (1); + } + DELAY(1000); + } + + return (0); + } + + /* + * Set the domain for the card. + * Domains 0x000-0x0ff are add-hoc. + * Domains 0x100-0x1ff are to an access point. + */ + static int + cnw_setdomain(struct nw_softc *nw, int domain) + { + int s; + + if (domain & ~0x1ff) + return (EINVAL); + + nw->nw_domain = domain; + + if (nw->nw_socket < 0) + return (0); + + s = splnet(); + if (cnw_cmd(nw, NW_CMD_SET_DOMAIN, SA(domain), -1)) + goto wedged; + splx(s); + return (0); + wedged: + splx(s); + cnwprintf(nw, "controller wedged @ %d\n", wccline); + return (EBUSY); + } + + /* + * Set the scramble key for the card + */ + static int + cnw_setkey(struct nw_softc *nw, int key) + { + int s; + + if (key & ~0xffff) + return (EINVAL); + + nw->nw_skey = key; + + if (nw->nw_socket < 0) + return (0); + + s = splnet(); + if (cnw_cmd(nw, NW_CMD_SET_SKEY, SA(key), -1)) + goto wedged; + splx(s); + return (0); + wedged: + splx(s); + cnwprintf(nw, "controller wedged @ %d\n", wccline); + return (EBUSY); + } + + /* + * We recieved an interrupt indicating that a packet is ready to be read. + * read the packet. An oddity I have noticed is that some packets arrive + * as type 0x0811 instead of type 0x0800. I am not sure why, but convert + * these to 0x0800 so everyone else likes the packet. + */ + static void + cnw_recv(struct nw_softc *nw) + { + struct mbuf *m; + struct ether_header *eh; + + if ((m = mcopy_in(nw)) != NULL) { + #ifdef RECV_PKT_DEBUG + u_char *b = mtod(m, u_char *); + int n; + printf("cnw%d: read (%d)", nw->nw_unit, m->m_len); + for (n = 0; n < m->m_len; ++n, ++b) + if ((n & 0xf) == 0) + printf("\n%04x %02x", n, *b); + else + printf(" %02x", *b); + printf("\n"); + #endif + + nw->nw_if.if_ipackets++; + eh = mtod(m, struct ether_header *); + #if NBPFILTER > 0 + /* + * Check if there's a bpf filter listening on this interface. + * If so, hand off the raw packet to bpf. + */ + #if defined(__bsdi__) + if (nw->nw_if.if_bpf) + bpf_mtap(nw->nw_if.if_bpf, m); + #elif defined(__FreeBSD__) + if (nw->nw_if.if_bpf) + bpf_mtap(&nw->nw_if, m); + #endif + #endif /*NBPFILTER*/ + + /* + * Note that the interface cannot be in promiscuous mode if + * there are no bpf listeners. And if we are in promiscuous + * mode, we have to check if this packet is really ours. + * + * XXX This test does not support multicasts. + */ + if ((nw->nw_if.if_flags & IFF_PROMISC) + && bcmp(eh->ether_dhost, nw->nw_addr, sizeof(eh->ether_dhost)) + #ifdef MULTICAST + && !ETHER_IS_MULTICAST(eh->ether_dhost) /*also non-broadcast*/ + #else + && bcmp(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dst)) + #endif + ) { + m_freem(m); + return; + } + + #if defined(__bsdi__) + eh->ether_type = ntohs(eh->ether_type); + if (eh->ether_type == 0x811) { + cnwprintf(nw, "converted packet from type 0x0811\n"); + eh->ether_type = 0x800; + } + m_adj(m, sizeof(struct ether_header)) ; + cnwprintf(nw, "recieved packet of type %04x\n", eh->ether_type); + #elif defined(__FreeBSD__) + /* ick! freebsd's ether_input expects ether_type in + network byte order */ + if (ntohs(eh->ether_type) == 0x811) { + cnwprintf(nw, "converted packet from type 0x0811\n"); + eh->ether_type = htons(0x800); + } + m_adj(m, sizeof(struct ether_header)) ; + cnwprintf(nw, "recieved packet of type %04x\n", ntohs(eh->ether_type)); + #endif + + ether_input(&nw->nw_if, eh, m) ; + } + } + + /* + * Send out a command, terminated by a -1. + * Normally each argument is a single unsigned byte, however, when we + * need to send out a short the bit SHORT_ARG will be sent and we + * need to split the short into two bytes. The macro SA(x) will or in + * the SHORT_ARG bit to x. + */ + static int + cnw_cmd(struct nw_softc *nw, ...) + { + volatile struct nwreg *nwr = nw->nw_reg; + va_list ap; + int i, c; + + if (WCC(nw->nw_creg)) { + printf("cnw%d: controller wedged\n", nw->nw_unit); + return (1); + } + + va_start(ap, nw); + i = 0; + while ((c = va_arg(ap, int)) != -1) { + nwr->nwr_cmd[i++] = c; + if (c & SHORT_ARG) + nwr->nwr_cmd[i++] = c >> 8; + } + nwr->nwr_cmd[i] = 0; /* No more commands. */ + va_end(ap); + return (0); + } + + /* + * Wait for command completion + */ + static int + cnw_cwait(volatile struct nwcreg *nwc) + { + register int rv = 0x10000; + + while ((nwc->nwc_isr & NWR_READY) == 0 && rv-- > 0) + (void)inb(0x61); + + return (rv == 0); + } + + /* + * debug print routine. It takes a normal printf style format string + * an prepends the unit name before printing it out. + */ + static void + _cnwprintf(struct nw_softc *nw, char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + #if defined(__bsdi__) + if (nw != NULL) + printf("cnw%d: %r", nw->nw_unit, fmt, ap); + else + printf("%r", fmt, ap); + #elif defined(__FreeBSD__) + if (nw != NULL) { + printf("cnw%d: ", nw->nw_unit); + vprintf(fmt, ap); + } + else + vprintf(fmt, ap); + #endif + va_end(ap); + } + + /* + * Copy the specified mbuf to the next available transmit buffer + * We have already verified there is a transmit buffer available. + */ + static int + mcopy_out(struct nw_softc *nw, struct mbuf *m0) + { + volatile struct nwreg *nwr = nw->nw_reg; + volatile u_char *bp; + u_short nb; + int len, n, xlen, ml; + u_short buffer, buflen, bufoff; + struct mbuf *m = m0; + char *mp; + + buffer = nwr->nwr_tbuffer; + buflen = nwr->nwr_tlen; + bufoff = nwr->nwr_toff; + + #if 0 /*toku*/ + len = m->m_pkthdr.len; + #else + for (len = 0, m = m0; m; m = m->m_next) + len += m->m_len; + #endif + + cnwprintf(nw, "mcopy_out %d bytes to buffer %x, off %x, len %d\n", + len, buffer, bufoff, buflen); + + nb = 0; + bp = NULL; /* this keeps gcc2 happy */ + xlen = 0; + + m = m0; + ml = m->m_len; + mp = mtod(m, char *); + cnwprintf2(nw, "got an mbuf of %d bytes\n", ml); + + while (m) { + if (nb == 0) { + cnwprintf2(nw, "Copy out buffer %x\n", buffer); + bp = (u_char *)nwr + buffer; + buffer = *(u_short *)bp; + bp += bufoff; + nb = buflen; + cnwprintf2(nw, "buffer has %d bytes (need %d more)\n", + nb, len - xlen); + } + n = nb < ml ? nb : ml; + #ifdef DIAGNOSTIC + if (xlen + n > len) { + printf("cnw%d: mbuf overrun. Wanted to copy %d bytes of len %d\n", nw->nw_unit, xlen + n, len); + break; + } + #endif + bcopy(mp, (void *)bp, n); + ml -= n; + mp += n; + if (ml == 0 && (m = m->m_next) != NULL) { + cnwprintf2(nw, "got an mbuf of %d bytes\n", ml); + ml = m->m_len; + mp = mtod(m, char *); + } + bp += n; + nb -= n; + xlen += n; + cnwprintf2(nw, "copied %d of %d bytes\n", xlen, len); + } + m_freem(m0); + return (xlen < len ? 0 : len); + } + + /* + * Copy the next packet into an mbuf and release the associated buffers + */ + static struct mbuf * + mcopy_in(struct nw_softc *nw) + { + volatile struct nwreg *nwr = nw->nw_reg; + volatile u_char *bp; + char *mp; + u_short nb, buffer; + int len, n; + struct mbuf *m, *m0, *m1; + + m0 = NULL; + + if (WCC(nw->nw_creg)) goto wedged; + + len = nwr->nwr_rlen; + buffer = nwr->nwr_rbuffer; + cnwprintf(nw, "recieve buffer %x length %d\n", buffer, len); + #ifdef CNW_TRAIL + trail[head].what = NW_CMD_RX_RELEASE; + trail[head].length = len; + microtime(&trail[head].when); + if (++head == 128) + head = 0; + #endif + + if (len <= 0 || len > nw->nw_if.if_mtu + 14) + goto bad; + + MGETHDR(m0, M_DONTWAIT, MT_DATA); + if (m0 != NULL && len + 2 > MHLEN) { + MCLGET(m0, M_DONTWAIT); + cnwprintf2(nw, "using an mbuf cluster\n"); + if ((m0->m_flags & M_EXT) == 0) { + printf("cnw%d: out of mbuf clusters\n", nw->nw_unit); + goto bad; + } + } + + if (m0 == NULL) + goto bad; + + m = m0; + m->m_pkthdr.rcvif = &nw->nw_if; + m->m_pkthdr.len = len; + + /* + * The ethernet header is 14 bytes long. Since we want the + * IP header on a 4 byte boundry, start 2 bytes in + */ + m->m_data += 2; + m->m_len = 0; + nb = 0; + bp = NULL; /* keep gcc2 happy */ + mp = mtod(m, char *); + + while (len > 0) { + if (nb == 0) { + cnwprintf2(nw, "Copy buffer %x\n", buffer); + #ifdef DIAGNOSTIC + if (buffer < 0x200 || buffer > 0x8000) + goto bad; + #endif + bp = (u_char *)nwr + buffer; + buffer = *(u_short *)bp; + nb = *(u_short *)(bp+2); + cnwprintf2(nw, "buffer has %d bytes (need %d more)\n", + nb, len); + bp += *(u_short *)(bp+4); + } + + n = len < nb ? len : nb; + if (M_TRAILINGSPACE(m) == 0) { + MGET(m1, M_DONTWAIT, MT_DATA); + if (m1 != NULL && len > MLEN) + MCLGET(m1, M_DONTWAIT); + if (m1 == NULL) + goto bad; + m->m_next = m1; + m = m1; + m->m_len = 0; + mp = mtod(m, char *); + } + if (M_TRAILINGSPACE(m) < n) + n = M_TRAILINGSPACE(m); + + bcopy((void *)bp, mp, n); + m->m_len += n; + len -= n; + bp += n; + mp += n; + nb -= n; + } + + if (0) { + bad: + if (m0) + m_freem(m0); + m0 = NULL; + } + + if (cnw_cmd(nw, NW_CMD_RX_RELEASE, -1)) + goto wedged; + return (m0); + + wedged: + cnwprintf(nw, "controller wedged @ %d\n", wccline); + if (m0) + m_freem(m0); + return (NULL); + } + + #ifdef USEVBCMP + static int + vbcmp(char volatile *p1, char volatile *p2, int s) + { + int r = 0; + + while (s-- > 0) + if ((r = (*p1++ - *p2++)) != 0) + break; + return (r); + } + + static void + vbcopy(char volatile *p1, char volatile *p2, int s) + { + while (s-- > 0) + *p2++ = *p1++; + } + #endif + + #endif /* !defined(__FreeBSD__) || NCNW > 0 */ Index: PAO/sys/i386/isa/if_cnwioctl.h diff -c /dev/null PAO/sys/i386/isa/if_cnwioctl.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:50 1998 --- PAO/sys/i386/isa/if_cnwioctl.h Sun Dec 6 07:47:11 1998 *************** *** 0 **** --- 1,52 ---- + /* BSDI $Id: if_cnwioctl.h,v 1.1.8.1 1998/12/05 22:47:11 itojun Exp $ */ + struct cnwstatus { + struct ifreq ifr; + u_char data[0x100]; + }; + + struct cnwstats { + u_int nws_rx; + u_int nws_rxerr; + u_int nws_rxoverflow; + u_int nws_rxoverrun; + u_int nws_rxcrcerror; + u_int nws_rxframe; + u_int nws_rxerrors; + u_int nws_rxavail; + u_int nws_rxone; + u_int nws_tx; + u_int nws_txokay; + u_int nws_txabort; + u_int nws_txlostcd; + u_int nws_txerrors; + u_int nws_txretries[16]; + }; + + struct cnwistats { + struct ifreq ifr; + struct cnwstats stats; + }; + + struct cnwtrail { + u_char what; + u_char status; + u_short length; + struct timeval when; + struct timeval done; + }; + + struct cnwitrail { + struct ifreq ifr; + int head; + struct cnwtrail trail[128]; + }; + + #define ifr_domain ifr_ifru.ifru_flags /* domain */ + #define ifr_key ifr_ifru.ifru_flags /* scramble key */ + + #define SIOCSCNWDOMAIN _IOW('i', 254, struct ifreq) /* set domain */ + #define SIOCGCNWDOMAIN _IOWR('i', 253, struct ifreq) /* get domain */ + #define SIOCSCNWKEY _IOWR('i', 252, struct ifreq) /* set scramble key */ + #define SIOCGCNWSTATUS _IOWR('i', 251, struct cnwstatus)/* get raw status */ + #define SIOCGCNWSTATS _IOWR('i', 250, struct cnwistats)/* get stats */ + #define SIOCGCNWTRAIL _IOWR('i', 249, struct cnwitrail)/* get trail */ Index: PAO/sys/i386/isa/if_cnwreg.h diff -c /dev/null PAO/sys/i386/isa/if_cnwreg.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:50 1998 --- PAO/sys/i386/isa/if_cnwreg.h Sun Dec 6 07:47:12 1998 *************** *** 0 **** --- 1,213 ---- + /* + * Copyright (c) 1996 Berkeley Software Design, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that this notice is retained, + * the conditions in the following notices are met, and terms applying + * to contributors in the following notices also apply to Berkeley + * Software Design, Inc. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by + * Berkeley Software Design, Inc. + * 4. Neither the name of the Berkeley Software Design, Inc. nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * BSDI $Id: if_cnwreg.h,v 1.1.8.1 1998/12/05 22:47:12 itojun Exp $ + * + * This driver is derived from a generic frame work which is + * Copyright(c) 1994,1995,1996 + * Yoichi Shinoda, Yoshitaka Tokugawa, WIDE Project, Wildboar Project + * and Foretune. All rights reserved. + * + * A linux driver was used as the "hardware reference manual" and + * is copyright by: + * + * John Markus Bjxrndalen + * Department of Computer Science + * University of Tromsx + * Norway + * johnm@staff.cs.uit.no, http://www.cs.uit.no/~johnm/ + */ + + /* + * Netwave AirSurfer Wireless LAN + * (Formerly known as the Xircom CreditCard Netwave Adapter) + */ + + /* + * Memory based control registers + */ + #define NW_MEM_ADDR 0x20000 + + struct nwreg { + /*000*/ u_char nwr_rsv00[0x100]; + /*100*/ u_char nwr_cmd[0x10]; /* Command buffer (write) */ + /*110*/ u_char nwr_rsv01[4]; + u_char nwr_runstate; /* Run state (write) */ + # define NWR_RUN 0x00 + # define NWR_READY 0x08 /* Ready for command/status read */ + # define NWR_HALT 0x40 + u_char nwr_rsv02[11]; + + /*120*/ u_char nwr_rstat; /* status on rx interrupt */ + #define NWR_RSTAT_RXAVAIL 0x80 + #define NWR_RSTAT_RXERROR 0x40 + #define NWR_RSTAT_OVERFLOW 0x10 + #define NWR_RSTAT_OVERRUN 0x08 + #define NWR_RSTAT_CRCERR 0x04 + #define NWR_RSTAT_FRAME 0x02 + u_char nwr_rsv03[3]; + u_char nwr_rclr; /* bits to clear in rstat (write) */ + u_char nwr_rsv04[11]; + + /*130*/ u_char nwr_tstat; /* status on tx interrupt */ + #define NWR_TSTAT_ABORT 0x80 /* abort */ + #define NWR_TSTAT_CARRLOST 0x40 /* No access point */ + #define NWR_TSTAT_OKAY 0x20 /* packet sent okay */ + #define NWR_TSTAT_TERR 0x10 /* Trasmitter error summary */ + #define NWR_TSTAT_RETRYMASK 0x0f + u_char nwr_rsv05[3]; + u_char nwr_tclr; /* bits to clear in tstat (write) */ + u_char nwr_rsv06[11]; + + /*140*/ u_short nwr_tbuffer; /* first available transmit buffer */ + u_short nwr_tlen; /* data bytes per buffer */ + u_short nwr_toff; /* starting offset into buffer */ + u_char nwr_rsv07[8]; + u_char nwr_lif; /* link integrity field */ + u_char nwr_rsv08[1]; + + /*150*/ short nwr_rlen; /* length of recieved packet */ + short nwr_rbuffer; /* first receive buffer of list */ + u_char nwr_spcq; /* connection quality? */ + u_char nwr_spu; + u_char nwr_isplq; /* link quality? */ + u_char nwr_rsv09[1]; + u_char nwr_hhc; + u_char nwr_rsv10[7]; + + /*160*/ u_char nwr_addr[6]; /* boards ethernet address */ + u_short nwr_rev[2]; /* revision number */ + u_char nwr_rsv11[1]; + u_char nwr_mhs; + u_char nwr_rsv12[2]; + char nwr_id[2]; /* boards id (NW) */ + + /*170*/ short nwr_bmemlen; + short nwr_bmembas; + u_char nwr_rsv13[12]; + + /*180*/ u_short nwr_rsv14[2]; + u_short nwr_rxerr; /* # of recieve errors */ + u_short nwr_frame; /* # of framing errors */ + u_short nwr_ihb; /* input heart beat count */ + u_short nwr_rsv15[2]; + u_short nwr_rxbufs; /* # of buffers received */ + /*190*/ u_short nwr_rxmulti; /* # of multi-buffer packets */ + u_short nwr_txretries; /* # of transmit retries */ + u_short nwr_txabort; /* # of transmit aborts */ + u_short nwr_rsv16[1]; + u_short nwr_ohb; /* output heart beat count */ + u_short nwr_txokay; /* # of transmits okay */ + u_short nwr_txsent; /* # of transmits requested */ + u_short nwr_rsv17[1]; + /*1A0*/ + }; + + /* + * ioport/memory based control registers + * These can either be gotten to by ioports or by memory mapping + */ + + #define NW_REG_ADDR 0x28000 + + struct nwcreg { + /*00*/ u_char nwc_enable; /* Interrupt enable register */ + # define NWR_IENA 0x01 /* Interrupt enable */ + # define NWR_LVLREQ 0x40 /* Level request */ + # define NWR_ENORMAL (NWR_IENA | NWR_LVLREQ) + /*01*/ u_char nwc_rsv00[1]; + /*02*/ u_char nwc_ccsr; /* command complete status register */ + # define NWR_IREADY 0x02 /* Interrupt Ready */ + /*03*/ u_char nwc_rsv01[1]; + /*04*/ u_char nwc_isr; /* interupt status register */ + # define NWR_RXAVAIL 0x80 /* Packet Received */ + # define NWR_RXERR 0x40 /* Receive status change */ + # define NWR_TXSTAT 0x20 /* Transmit status change */ + # define NWR_READY 0x08 /* Ready for command/status read */ + # define NWR_TXEMP 0x01 /* Transmit descriptor available */ + /*05*/ u_char nwc_rsv02[1]; + /*06*/ u_short nwc_io; + /*08*/ u_char nwc_ioctl; + /*09*/ u_char nwc_rsv03[1]; + /*0A*/ u_char nwc_ictrl; /* interrupt control register */ + # define NWR_IDISABLE 0x00 + # define NWR_IENABLE 0x02 + # define NWR_IDISUS 0x10 /* make unused sources not interrupt */ + # define NWR_INORMAL (NWR_IENABLE | NWR_IDISUS) + /*0B*/ u_char nwc_rsv04[1]; + /*0C*/ u_char nwc_reset; /* resetting runstate */ + # define NWR_RESET 0x80 + # define NWR_NOTRESET 0 + /*0D*/ u_char nwc_rsv05[3]; + }; + + + /* command bytes */ + + #define SHORT_ARG 0x10000 /* Argument is 16 bits, not 8 */ + #define SA(x) (x | SHORT_ARG) + + #define NW_CMD_INIT 0x0 /* Initialize */ + #define NW_CMD_SET_RXMODE 0x1 /* Set receive mode */ + # define NW_RXENA 0x80 /* Receive Enable */ + # define NW_RXMAC 0x20 /* MAC host receive mode*/ + # define NW_RXPROM 0x10 /* Promiscuous */ + # define NW_RXMCAST 0x08 /* Accept Multicast Packets */ + # define NW_RXBCAST 0x04 /* Accept Broadcast Packets */ + /* + * Determine the default receive mode + */ + # define NW_RXMODE(nw) ((nw->nw_if.if_flags & IFF_PROMISC) ? \ + (NW_RXENA | NW_RXMCAST | NW_RXBCAST | NW_RXPROM) : \ + (NW_RXENA | NW_RXMCAST | NW_RXBCAST)) + + #define NW_CMD_SET_TXMODE 0x2 /* Set transmit mode */ + # define NW_TXENA 0x80 /* Transmit Enable */ + # define NW_TXMAC 0x20 /* Host sends MAC mode */ + # define NW_TXUDATA 0x10 /* Enable Uni-Data packets */ + # define NW_TXSCRAMBLE 0x02 /* Scramble data packets */ + # define NW_TXLOOPBACK 0x01 /* Loopback mode */ + #define NW_CMD_ADD_MCADDR 0x3 /* Add mc addr */ + #define NW_CMD_DEL_MCADDR 0x4 /* Delete mc addr */ + #define NW_CMD_MC_CTRL 0x5 /* Enable/Disable mc (?) */ + #define NW_CMD_RUN 0x6 /* You can move */ + #define NW_CMD_HALT 0x7 /* Don't move */ + #define NW_CMD_TX_START 0x8 /* Start tx on current tx desc */ + #define NW_CMD_RX_RELEASE 0x9 /* Release current rx desc */ + #define NW_CMD_SET_SKEY 0xa /* Set scramble key */ + #define NW_CMD_SET_DOMAIN 0xb /* Set domain */ + # define NW_ACCESSPOINT 0x100 /* Default access point domain */ + # define NW_ADDHOC 0x0 /* Default add hoc domain */ + # define NW_DOMAIN NW_ADDHOC /* Default domain */ Index: PAO/sys/i386/isa/if_ed.c diff -c PAO/sys/i386/isa/if_ed.c:1.1.1.4 PAO/sys/i386/isa/if_ed.c:1.1.1.4.2.1 *** PAO/sys/i386/isa/if_ed.c:1.1.1.4 Sat Dec 5 05:37:34 1998 --- PAO/sys/i386/isa/if_ed.c Sun Dec 6 07:47:14 1998 *************** *** 137,142 **** --- 137,143 ---- u_char rec_page_start; /* first page of RX ring-buffer */ u_char rec_page_stop; /* last page of RX ring-buffer */ u_char next_packet; /* pointer to next unread RX packet */ + u_char delay_output; struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */ }; *************** *** 165,175 **** void *ed_attach_NE2000_pci __P((int, int)); #endif - #include "card.h" - #if NCARD > 0 - static int ed_probe_pccard __P((struct isa_device *, u_char *)); - #endif - static void ds_getmcaf __P((struct ed_softc *, u_long *)); static void ed_get_packet(struct ed_softc *, char *, /* u_short */ int, int); --- 166,171 ---- *************** *** 196,201 **** --- 192,200 ---- static u_long ds_crc(u_char *ep); + static int ed_get_Linksys __P((struct ed_softc *)); + + #include "card.h" #if NCARD > 0 #include #include *************** *** 205,210 **** --- 204,211 ---- /* * PC-Card (PCMCIA) specific code. */ + static int ed_probe_pccard __P((struct pccard_devinfo *)); + static int ed_attach_pccard __P((struct pccard_devinfo *)); static int edinit(struct pccard_devinfo *); /* init device */ static void edunload(struct pccard_devinfo *); /* Disable driver */ static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ *************** *** 227,245 **** static int edinit(struct pccard_devinfo *devi) { ! struct ed_softc *sc = &ed_softc[devi->isahd.id_unit]; /* validate unit number. */ ! if (devi->isahd.id_unit >= NED) return(ENODEV); /* * Probe the device. If a value is returned, the * device was found at the location. */ sc->gone = 0; ! if (ed_probe_pccard(&devi->isahd, devi->misc) == 0) return(ENXIO); ! if (ed_attach_isa(&devi->isahd) == 0) return(ENXIO); return(0); --- 228,257 ---- static int edinit(struct pccard_devinfo *devi) { ! int i; ! u_char e; ! struct ed_softc *sc; ! int unit = devi->pd_unit; /* validate unit number. */ ! if (unit >= NED) return(ENODEV); + sc = &ed_softc[unit]; + /* * Probe the device. If a value is returned, the * device was found at the location. */ sc->gone = 0; ! if (ed_probe_pccard(devi)==0) return(ENXIO); ! e = 0; ! for (i = 0; i < ETHER_ADDR_LEN; ++i) ! e |= devi->misc[i]; ! if (e) ! for (i = 0; i < ETHER_ADDR_LEN; ++i) ! sc->arpcom.ac_enaddr[i] = devi->misc[i]; ! if (ed_attach_pccard(devi) == 0) return(ENXIO); return(0); *************** *** 257,273 **** static void edunload(struct pccard_devinfo *devi) { ! struct ed_softc *sc = &ed_softc[devi->isahd.id_unit]; ! struct ifnet *ifp = &sc->arpcom.ac_if; if (sc->gone) { ! printf("ed%d: already unloaded\n", devi->isahd.id_unit); return; } ifp->if_flags &= ~IFF_RUNNING; if_down(ifp); sc->gone = 1; ! printf("ed%d: unload\n", devi->isahd.id_unit); } /* --- 269,291 ---- static void edunload(struct pccard_devinfo *devi) { ! struct ed_softc *sc; ! struct ifnet *ifp; ! int unit = devi->pd_unit; ! ! if (unit >= NED) ! return; ! sc = &ed_softc[unit]; ! ifp = &sc->arpcom.ac_if; if (sc->gone) { ! printf("ed%d: already unloaded\n", unit); return; } ifp->if_flags &= ~IFF_RUNNING; if_down(ifp); sc->gone = 1; ! printf("ed%d: unload\n", unit); } /* *************** *** 277,283 **** static int card_intr(struct pccard_devinfo *devi) { ! edintr_sc(&ed_softc[devi->isahd.id_unit]); return(1); } #endif /* NCARD > 0 */ --- 295,301 ---- static int card_intr(struct pccard_devinfo *devi) { ! edintr_sc(&ed_softc[devi->pd_unit]); return(1); } #endif /* NCARD > 0 */ *************** *** 1060,1065 **** --- 1078,1101 ---- return (ED_3COM_IO_PORTS); } + static int + ed_get_Linksys(sc) + struct ed_softc *sc; + { + u_char sum; + int i; + + for (sum = 0, i = 0x14; i < 0x1c; i++) + sum += inb(sc->nic_addr + i); + if (sum != 0xff) + return 0; + for (i = 0; i < ETHER_ADDR_LEN; i++) { + sc->arpcom.ac_enaddr[i] = inb(sc->nic_addr + 0x14 + i); + /* printf("%02x.", sc->arpcom.ac_enaddr[i]); */ + } + return 2; + } + /* * Probe and vendor-specific initialization routine for NE1000/2000 boards */ *************** *** 1074,1079 **** --- 1110,1116 ---- u_char romdata[16], tmp; static char test_pattern[32] = "THIS is A memory TEST pattern"; char test_buffer[32]; + int linksys = 0; sc->asic_addr = port + ED_NOVELL_ASIC_OFFSET; sc->nic_addr = port + ED_NOVELL_NIC_OFFSET; *************** *** 1164,1176 **** sc->type = ED_TYPE_NE2000; sc->type_str = "NE2000"; ! } else { sc->type = ED_TYPE_NE1000; sc->type_str = "NE1000"; } /* 8k of memory plus an additional 8k if 16bit */ ! memsize = 8192 + sc->isa16bit * 8192; #if 0 /* probably not useful - NE boards only come two ways */ /* allow kernel config file overrides */ --- 1201,1222 ---- sc->type = ED_TYPE_NE2000; sc->type_str = "NE2000"; ! } ! #if NCARD > 0 ! else if (linksys = ed_get_Linksys(sc)) { ! outb(sc->nic_addr + ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); ! sc->isa16bit = 1; ! sc->type = ED_TYPE_NE2000; ! sc->type_str = "Linksys"; ! } ! #endif /* NCARD > 0 */ ! else { sc->type = ED_TYPE_NE1000; sc->type_str = "NE1000"; } /* 8k of memory plus an additional 8k if 16bit */ ! memsize = 8192 + (sc->isa16bit + linksys) * 8192; #if 0 /* probably not useful - NE boards only come two ways */ /* allow kernel config file overrides */ *************** *** 1184,1190 **** /* The start address is tied to the bus width */ sc->mem_start = (char *) 8192 + sc->isa16bit * 8192; sc->mem_end = sc->mem_start + memsize; ! sc->tx_page_start = memsize / ED_PAGE_SIZE; #ifdef GWETHER { --- 1230,1236 ---- /* The start address is tied to the bus width */ sc->mem_start = (char *) 8192 + sc->isa16bit * 8192; sc->mem_end = sc->mem_start + memsize; ! sc->tx_page_start = (u_int) sc->mem_start / ED_PAGE_SIZE; #ifdef GWETHER { *************** *** 1256,1271 **** if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) sc->txb_cnt = 1; else ! sc->txb_cnt = 2; sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; ! sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE; sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; ! ed_pio_readmem(sc, 0, romdata, 16); ! for (n = 0; n < ETHER_ADDR_LEN; n++) ! sc->arpcom.ac_enaddr[n] = romdata[n * (sc->isa16bit + 1)]; #ifdef GWETHER if (sc->arpcom.ac_enaddr[2] == 0x86) { --- 1302,1320 ---- if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) sc->txb_cnt = 1; else ! sc->txb_cnt = 2 + linksys; sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; ! n = sc->tx_page_start + memsize / ED_PAGE_SIZE; ! sc->rec_page_stop = (n > 0xff) ? 0xff : n; sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; ! if (!linksys) { ! ed_pio_readmem(sc, 0, romdata, 16); ! for (n = 0; n < ETHER_ADDR_LEN; n++) ! sc->arpcom.ac_enaddr[n] = romdata[n * (sc->isa16bit + 1)]; ! } #ifdef GWETHER if (sc->arpcom.ac_enaddr[2] == 0x86) { *************** *** 1297,1319 **** * supplied (from the CIS), relying on the probe to find it instead. */ static int ! ed_probe_pccard(isa_dev, ether) ! struct isa_device *isa_dev; ! u_char *ether; { ! int nports; ! nports = ed_probe_WD80x3(isa_dev); if (nports) return (nports); ! nports = ed_probe_Novell(isa_dev); if (nports) return (nports); return (0); } #endif /* NCARD > 0 */ #define ED_HPP_TEST_SIZE 16 --- 1346,1382 ---- * supplied (from the CIS), relying on the probe to find it instead. */ static int ! ed_probe_pccard(devi) ! struct pccard_devinfo *devi; { ! struct ed_softc *sc = &ed_softc[devi->pd_unit]; ! int nports; ! nports = ed_probe_Novell_generic(sc, devi->pd_iobase, ! devi->pd_unit, devi->pd_flags); if (nports) return (nports); ! #if 0 ! nports = ed_probe_WD80x3(isa_dev); if (nports) return (nports); + #endif return (0); } + static int + ed_attach_pccard(devi) + struct pccard_devinfo *devi; + { + struct ed_softc *sc = &ed_softc[devi->pd_unit]; + int unit = devi->pd_unit; + int port = devi->pd_iobase; + int isa_flags = devi->pd_flags; + + return ed_attach(sc, unit, isa_flags); + } #endif /* NCARD > 0 */ #define ED_HPP_TEST_SIZE 16 *************** *** 1645,1650 **** --- 1708,1715 ---- { struct ifnet *ifp = &sc->arpcom.ac_if; + sc->delay_output = (flags & ED_FLAGS_DELAY_OUTPUT); + /* * Set interface to stopped condition (reset) */ *************** *** 2931,2937 **** * irrecoverably jamming the ISA bus. */ while (((inb(sc->nic_addr + ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) && --maxwait); ! } else if ((sc->vendor == ED_VENDOR_HP) && (sc->type == ED_TYPE_HP_PCLANPLUS)) { --- 2996,3003 ---- * irrecoverably jamming the ISA bus. */ while (((inb(sc->nic_addr + ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) && --maxwait); ! if (sc->delay_output) ! DELAY(5); } else if ((sc->vendor == ED_VENDOR_HP) && (sc->type == ED_TYPE_HP_PCLANPLUS)) { Index: PAO/sys/i386/isa/if_edreg.h diff -c PAO/sys/i386/isa/if_edreg.h:1.1.1.2 PAO/sys/i386/isa/if_edreg.h:1.1.1.2.2.1 *** PAO/sys/i386/isa/if_edreg.h:1.1.1.2 Sat Dec 5 05:37:36 1998 --- PAO/sys/i386/isa/if_edreg.h Sun Dec 6 07:47:16 1998 *************** *** 598,603 **** --- 598,610 ---- #define ED_FLAGS_FORCE_PIO 0x0010 /* + * This flag is for cards with incomplete DMA status register. I don't + * know whether it works, but Linux PCMCIA package has this flag. + * Tatsumi Hosokawa (hosokawa@jp.FreeBSD.org) + */ + #define ED_FLAGS_DELAY_OUTPUT 0x0020 + + /* * Definitions for Western digital/SMC WD80x3 series ASIC */ /* *************** *** 996,1001 **** --- 1003,1027 ---- * Reset register; reading from this register causes a board reset */ #define ED_NOVELL_RESET 0x0f + + /* + * Definitions for PCCARD + */ + #define ED_PC_PAGE_OFFSET 0x40 /* page offset for NIC access to mem */ + #define ED_PC_IO_PORTS 32 + #define ED_PC_RESET 0x1f + #define ED_PC_MISC 0x18 + #define ED_PC_ASIC_OFFSET 0x10 + + /* + * if_ze.h constants + */ + + #define ZE_PAGE_OFFSET 0x40 /* mem buffer starts at 0x4000 */ + + #define ZE_DATA_IO 0x10 + #define ZE_MISC 0x18 + #define ZE_RESET 0x1F /* * Definitions for PCCARD Index: PAO/sys/i386/isa/if_ep.c diff -c PAO/sys/i386/isa/if_ep.c:1.1.1.4 PAO/sys/i386/isa/if_ep.c:1.1.1.4.2.1 *** PAO/sys/i386/isa/if_ep.c:1.1.1.4 Sat Dec 5 05:37:38 1998 --- PAO/sys/i386/isa/if_ep.c Sun Dec 6 07:47:17 1998 *************** *** 129,138 **** static void epinit __P((struct ep_softc *)); static void epread __P((struct ep_softc *)); ! void epreset __P((int)); static void epstart __P((struct ifnet *)); static void epstop __P((struct ep_softc *)); static void epwatchdog __P((struct ifnet *)); #if 0 static int send_ID_sequence __P((int)); --- 129,141 ---- static void epinit __P((struct ep_softc *)); static void epread __P((struct ep_softc *)); ! /*void epreset __P((int));*/ static void epstart __P((struct ifnet *)); static void epstop __P((struct ep_softc *)); static void epwatchdog __P((struct ifnet *)); + static size_t ep_countmcast __P((struct ep_softc *)); + static void ep_setmcast __P((struct ep_softc *)); + /*void epintr(int unit);*/ #if 0 static int send_ID_sequence __P((int)); *************** *** 189,219 **** ep_pccard_init(devi) struct pccard_devinfo *devi; { ! struct isa_device *is = &devi->isahd; ! struct ep_softc *sc = ep_softc[is->id_unit]; struct ep_board *epb; int i; ! epb = &ep_board[is->id_unit]; if (sc == 0) { ! if ((sc = ep_alloc(is->id_unit, epb)) == 0) { return (ENXIO); } ep_unit++; } /* get_e() requires these. */ ! sc->ep_io_addr = is->id_iobase; ! sc->unit = is->id_unit; ! epb->epb_addr = is->id_iobase; epb->epb_used = 1; epb->prod_id = get_e(sc, EEPROM_PROD_ID); /* 3C589's product id? */ if (epb->prod_id != 0x9058) { ! printf("ep%d: failed to come ready.\n", is->id_unit); return (ENXIO); } --- 192,221 ---- ep_pccard_init(devi) struct pccard_devinfo *devi; { ! struct ep_softc *sc = ep_softc[devi->pd_unit]; struct ep_board *epb; int i; ! epb = &ep_board[devi->pd_unit]; if (sc == 0) { ! if ((sc = ep_alloc(devi->pd_unit, epb)) == 0) { return (ENXIO); } ep_unit++; } /* get_e() requires these. */ ! sc->ep_io_addr = devi->pd_iobase; ! sc->unit = devi->pd_unit; ! epb->epb_addr = devi->pd_iobase; epb->epb_used = 1; epb->prod_id = get_e(sc, EEPROM_PROD_ID); /* 3C589's product id? */ if (epb->prod_id != 0x9058) { ! printf("ep%d: failed to come ready.\n", devi->pd_unit); return (ENXIO); } *************** *** 232,243 **** ep_pccard_attach(devi) struct pccard_devinfo *devi; { ! struct isa_device *is = &devi->isahd; ! struct ep_softc *sc = ep_softc[is->id_unit]; u_short config; sc->ep_connectors = 0; ! config = inw(IS_BASE + EP_W0_CONFIG_CTRL); if (config & IS_BNC) { sc->ep_connectors |= BNC; } --- 234,244 ---- ep_pccard_attach(devi) struct pccard_devinfo *devi; { ! struct ep_softc *sc = ep_softc[devi->pd_unit]; u_short config; sc->ep_connectors = 0; ! config = inw(devi->pd_iobase + EP_W0_CONFIG_CTRL); if (config & IS_BNC) { sc->ep_connectors |= BNC; } *************** *** 266,280 **** ep_unload(devi) struct pccard_devinfo *devi; { ! struct ep_softc *sc = ep_softc[devi->isahd.id_unit]; if (sc->gone) { ! printf("ep%d: already unloaded\n", devi->isahd.id_unit); return; } sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; sc->gone = 1; ! printf("ep%d: unload\n", devi->isahd.id_unit); } /* --- 267,281 ---- ep_unload(devi) struct pccard_devinfo *devi; { ! struct ep_softc *sc = ep_softc[devi->pd_unit]; if (sc->gone) { ! printf("ep%d: already unloaded\n", devi->pd_unit); return; } sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; sc->gone = 1; ! printf("ep%d: unload\n", devi->pd_unit); } /* *************** *** 285,291 **** card_intr(devi) struct pccard_devinfo *devi; { ! epintr(devi->isahd.id_unit); return(1); } #endif /* NCARD > 0 */ --- 286,292 ---- card_intr(devi) struct pccard_devinfo *devi; { ! epintr(devi->pd_unit); return(1); } #endif /* NCARD > 0 */ *************** *** 590,599 **** struct sockaddr_dl *sdl; u_short *p; int i; int attached; sc->gone = 0; ! attached = (ifp->if_softc != 0); printf("ep%d: ", sc->unit); /* --- 591,601 ---- struct sockaddr_dl *sdl; u_short *p; int i; + static int ep_attached[NEP]; int attached; sc->gone = 0; ! attached = ep_attached[sc->unit]; printf("ep%d: ", sc->unit); /* *************** *** 674,679 **** --- 676,682 ---- bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); } #endif + ep_attached[sc->unit] = 1; return 0; } *************** *** 734,745 **** outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); ! if (ifp->if_flags & IFF_PROMISC) ! outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | ! FIL_GROUP | FIL_BRDCST | FIL_ALL); ! else ! outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | ! FIL_GROUP | FIL_BRDCST); /* * S.B. --- 737,743 ---- outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); ! ep_setmcast(sc); /* * S.B. *************** *** 968,973 **** --- 966,979 ---- while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) { + #if NCARD > 0 + if (status == 0xffff) { + printf("ep%d: strange status - PC-card removed?\n", + sc->unit); + return; + } + #endif /* NCARD > 0 */ + /* first acknowledge all interrupt sources */ outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK)); *************** *** 1351,1362 **** } break; case SIOCADDMULTI: case SIOCDELMULTI: ! /* Now this driver has no support for programmable ! * multicast filters. If some day it will gain this ! * support this part of code must be extended. ! */ ! error = 0; break; default: error = EINVAL; --- 1357,1376 ---- } break; case SIOCADDMULTI: + error = ether_addmulti(ifr, &sc->arpcom); + if (error == ENETRESET) { + /* update multicast filter list. */ + ep_setmcast(sc); + error = 0; + } + break; case SIOCDELMULTI: ! error = ether_delmulti(ifr, &sc->arpcom); ! if (error == ENETRESET) { ! /* update multicast filter list. */ ! ep_setmcast(sc); ! error = 0; ! } break; default: error = EINVAL; *************** *** 1453,1458 **** --- 1467,1505 ---- for (i = 0; i < 16; i++) data = (data << 1) | (inw(id_port) & 1); return (data); + } + + static size_t + ep_countmcast(sc) + struct ep_softc *sc; + { + register struct ether_multi *enm; + register struct ether_multistep step; + size_t count; + + count = 0; + ETHER_FIRST_MULTI(step, &sc->arpcom, enm); + while (enm != NULL) { + count++; + ETHER_NEXT_MULTI(step, enm); + } + + return count; + } + + static void + ep_setmcast(sc) + struct ep_softc *sc; + { + struct ifnet *ifp = (struct ifnet *)sc; + u_short filter; + + filter = FIL_INDIVIDUAL | FIL_BRDCST; + if (ep_countmcast(sc) != 0) + filter |= FIL_GROUP; + if (ifp->if_flags & IFF_PROMISC) + filter |= FIL_ALL; + outw(BASE + EP_COMMAND, SET_RX_FILTER | filter); } #endif /* NEP > 0 */ Index: PAO/sys/i386/isa/if_fe.c diff -c PAO/sys/i386/isa/if_fe.c:1.1.1.3 PAO/sys/i386/isa/if_fe.c:1.1.1.3.4.1 *** PAO/sys/i386/isa/if_fe.c:1.1.1.3 Fri Jul 24 19:17:42 1998 --- PAO/sys/i386/isa/if_fe.c Sun Dec 6 07:47:18 1998 *************** *** 250,255 **** --- 250,256 ---- static void fe_start ( struct ifnet * ); static void fe_reset ( int ); static void fe_watchdog ( struct ifnet * ); + /*void feintr ( int unit );*/ /* Local functions. Order of declaration is confused. FIXME. */ static int fe_probe_fmv ( DEVICE *, struct fe_softc * ); *************** *** 356,362 **** struct fe_softc *sc; /* validate unit number. */ ! if (devi->isahd.id_unit >= NFE) return (ENODEV); /* * Probe the device. If a value is returned, --- 357,363 ---- struct fe_softc *sc; /* validate unit number. */ ! if (devi->pd_unit >= NFE) return (ENODEV); /* * Probe the device. If a value is returned, *************** *** 365,371 **** #if FE_DEBUG >= 2 printf("Start Probe\n"); #endif ! sc = &fe_softc[devi->isahd.id_unit]; memcpy(sc->sc_enaddr, devi->misc, ETHER_ADDR_LEN); if (fe_probe(&devi->isahd) == 0) return (ENXIO); --- 366,372 ---- #if FE_DEBUG >= 2 printf("Start Probe\n"); #endif ! sc = &fe_softc[devi->pd_unit]; memcpy(sc->sc_enaddr, devi->misc, ETHER_ADDR_LEN); if (fe_probe(&devi->isahd) == 0) return (ENXIO); *************** *** 390,398 **** static void feunload(struct pccard_devinfo *devi) { ! struct fe_softc *sc = &fe_softc[devi->isahd.id_unit]; ! printf("fe%d: unload\n", devi->isahd.id_unit); ! fe_stop(devi->isahd.id_unit); } /* --- 391,403 ---- static void feunload(struct pccard_devinfo *devi) { ! struct fe_softc *sc; ! int unit=devi->pd_unit; ! if (unit >= NFE) ! return; ! sc = &fe_softc[unit]; ! printf("fe%d: unload\n", unit); ! fe_stop(unit); } /* *************** *** 402,408 **** static int fe_card_intr(struct pccard_devinfo *devi) { ! feintr(devi->isahd.id_unit); return (1); } #endif /* NCARD > 0 */ --- 407,413 ---- static int fe_card_intr(struct pccard_devinfo *devi) { ! feintr(devi->pd_unit); return (1); } #endif /* NCARD > 0 */ Index: PAO/sys/i386/isa/if_sn.c diff -c /dev/null PAO/sys/i386/isa/if_sn.c:1.1.8.2 *** /dev/null Fri Dec 25 10:50:55 1998 --- PAO/sys/i386/isa/if_sn.c Wed Dec 23 12:00:16 1998 *************** *** 0 **** --- 1,1766 ---- + /* + * Copyright (c) 1996 Gardner Buchanan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Gardner Buchanan. + * 4. The name of Gardner Buchanan may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: if_sn.c,v 1.1.8.2 1998/12/23 03:00:16 itojun Exp $ + */ + + /* + * This is a driver for SMC's 9000 series of Ethernet adapters. + * + * This FreeBSD driver is derived from the smc9194 Linux driver by + * Erik Stahlman and is Copyright (C) 1996 by Erik Stahlman. + * This driver also shamelessly borrows from the FreeBSD ep driver + * which is Copyright (C) 1994 Herb Peyerl + * All rights reserved. + * + * It is set up for my SMC91C92 equipped Ampro LittleBoard embedded + * PC. It is adapted from Erik Stahlman's Linux driver which worked + * with his EFA Info*Express SVC VLB adaptor. According to SMC's databook, + * it will work for the entire SMC 9xxx series. (Ha Ha) + * + * "Features" of the SMC chip: + * 4608 byte packet memory. (for the 91C92. Others have more) + * EEPROM for configuration + * AUI/TP selection + * + * Authors: + * Erik Stahlman erik@vt.edu + * Herb Peyerl hpeyerl@novatel.ca + * Andres Vega Garcia avega@sophia.inria.fr + * Serge Babkin babkin@hq.icb.chel.su + * Gardner Buchanan gbuchanan@shl.com + * + * Sources: + * o SMC databook + * o "smc9194.c:v0.10(FIXED) 02/15/96 by Erik Stahlman (erik@vt.edu)" + * o "if_ep.c,v 1.19 1995/01/24 20:53:45 davidg Exp" + * + * Known Bugs: + * o The hardware multicast filter isn't used yet. + * o Setting of the hardware address isn't supported. + * o Hardware padding isn't used. + */ + + /* + * Modifications for Megahertz X-Jack Ethernet Card (XJ-10BT) + * + * Copyright (c) 1996 by Tatsumi Hosokawa + * BSD-nomads, Tokyo, Japan. + */ + /* + * Multicast support by Kei TANAKA + * Special thanks to itojun@itojun.org + */ + #include "sn.h" + #if NSN > 0 + + #undef SN_DEBUG /* (by hosokawa) */ + + #include "bpfilter.h" + + #include + #if defined(__FreeBSD__) + #include + #include + #endif + #include + #include + #include + #include + #include + #if defined(__NetBSD__) + #include + #endif + + #include + #include + #include + + #ifdef INET + #include + #include + #include + #include + #include + #endif + + #ifdef INET6 + #ifndef INET + #include + #endif + #include + #endif + + #ifdef NS + #include + #include + #endif + + #if NBPFILTER > 0 + #include + #include + #endif + + #if defined(__FreeBSD__) + #include + #endif + + #ifdef PC98 + #include + #else /*PC98*/ + #include + #endif /*PC98*/ + #include + #include + + /* PCCARD suport */ + #include "card.h" + #if NCARD > 0 + #include + #include + #include + #include + #endif /* NCARD > 0 */ + + #include + + /* for PCMCIA Ethernet */ + static int sn_pccard[NSN]; /* set to 1 if it's PCMCIA card */ + static u_char sn_pccard_macaddr[NSN][6]; + static int sn_import_macaddr[NSN]; + + static int snprobe __P((struct isa_device *)); + static int snattach __P((struct isa_device *)); + static int snioctl __P((struct ifnet * ifp, int, caddr_t)); + + static int smc_probe __P((int ioaddr, int pccard)); + static void snresume __P((struct ifnet *)); + + void sninit __P((int)); + void snintr __P((int)); + void snread __P((struct ifnet *)); + void snreset __P((int)); + void snstart __P((struct ifnet *)); + void snstop __P((int)); + void snwatchdog __P((struct ifnet *)); + + static void sn_setmcast(struct sn_softc *); + static int sn_getmcf(struct arpcom *ac, u_char *mcf); + static u_int smc_crc(u_char *); + + /* I (GB) have been unlucky getting the hardware padding + * to work properly. + */ + #define SW_PAD + + struct sn_softc sn_softc[NSN]; + + struct isa_driver sndriver = { + snprobe, + snattach, + "sn", + 0 + }; + + + /* PCCARD Support */ + #if NCARD > 0 + /* + * PC-Card (PCMCIA) specific code. + */ + static int sn_card_intr(struct pccard_devinfo *); /* Interrupt handler */ + static void snunload(struct pccard_devinfo *); /* Disable driver */ + static int sn_card_init(struct pccard_devinfo *); /* init device */ + + static struct pccard_device sn_info = + { + "sn", + sn_card_init, + snunload, + sn_card_intr, + 0, /* Attributes - presently unused */ + &net_imask /* Interrupt mask for device */ + /* This should also include net_imask?? */ + }; + + DATA_SET(pccarddrv_set, sn_info); + + static int + sn_card_init(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + struct sn_softc *sc = &sn_softc[devi->pd_unit]; + + sn_pccard[unit] = 1; + sn_import_macaddr[unit] = 0; + if (devi->misc[0] | devi->misc[1] | devi->misc[2]) { + int i; + for (i = 0; i < 6; i++) { + sn_pccard_macaddr[unit][i] = devi->misc[i]; + } + sn_import_macaddr[unit] = 1; + } + sc->gone = 0; + /* + * validate unit number. + */ + if (unit >= NSN) + return ENODEV; + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + #ifdef SN_DEBUG + printf("snprobe()\n"); + #endif + if (snprobe(&devi->isahd)==0) + return ENXIO; + #ifdef SN_DEBUG + printf("snattach()\n"); + #endif + if (snattach(&devi->isahd)==0) + return ENXIO; + /* initialize interface dynamically */ + sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen; + + return 0; + } + + static void + snunload(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + struct sn_softc *sc = &sn_softc[devi->pd_unit]; + + if (sc->gone) { + printf("sn%d: already unloaded.\n", unit); + return; + } + + snstop(unit); + sc->gone = 1; + sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; + printf("sn%d: unload.\n", unit); + } + + static int + sn_card_intr(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + snintr(unit); + return(1); + } + + #endif /* NCARD > 0 */ + + + int + snprobe(struct isa_device *is) + { + /* + * Device was configured with 'port ?' In this case we complain + */ + if (is->id_iobase == -1) { /* port? */ + printf("sn%d: SMC91Cxx cannot determine ioaddr\n", is->id_unit); + return 0; + } + /* + * Device was configured with 'irq ?' In this case we complain + */ + if (is->id_irq == 0) { + printf("sn%d: SMC91Cxx cannot determine irq\n", is->id_unit); + return (0); + } + /* + * Device was configured with 'port xxx', 'irq xx' In this case we + * search for the card with that address + */ + if (smc_probe(is->id_iobase, sn_pccard[is->id_unit]) != 0) + return (0); + + return (SMC_IO_EXTENT); + } + + + static int + snattach(struct isa_device *is) + { + struct sn_softc *sc = &sn_softc[is->id_unit]; + struct ifnet *ifp = &sc->arpcom.ac_if; + u_short i; + int j; + u_char *p; + struct ifaddr *ifa; + struct sockaddr_dl *sdl; + int rev; + u_short address; + #if NCARD > 0 + static int alredy_ifatch[NSN]; + #endif + + /* + * This is the value used for BASE + */ + sc->sn_io_addr = is->id_iobase; + + sc->pages_wanted = -1; + + printf("sn%d: ", is->id_unit); + + SMC_SELECT_BANK(3); + rev = inw(BASE + REVISION_REG_W); + if (chip_ids[(rev >> 4) & 0xF]) + printf("%s ", chip_ids[(rev >> 4) & 0xF]); + + SMC_SELECT_BANK(1); + i = inw(BASE + CONFIG_REG_W); + printf(i & CR_AUI_SELECT ? "AUI" : "UTP"); + + if (sn_import_macaddr[is->id_unit]) { + for (j = 0; j < 3; j++) { + u_short w; + + w = (u_short)sn_pccard_macaddr[is->id_unit][j * 2] | + (((u_short)sn_pccard_macaddr[is->id_unit][j * 2 + 1]) << 8); + outw(BASE + IAR_ADDR0_REG_W + j * 2, w); + } + } + + /* + * Read the station address from the chip. The MAC address is bank 1, + * regs 4 - 9 + */ + SMC_SELECT_BANK(1); + p = (u_char *) & sc->arpcom.ac_enaddr; + for (i = 0; i < 6; i += 2) { + address = inw(BASE + IAR_ADDR0_REG_W + i); + p[i + 1] = address >> 8; + p[i] = address & 0xFF; + } + printf(" MAC address %6D\n", sc->arpcom.ac_enaddr, ":"); + ifp->if_unit = is->id_unit; + ifp->if_name = "sn"; + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_output = ether_output; + ifp->if_start = snstart; + ifp->if_ioctl = snioctl; + ifp->if_watchdog = snwatchdog; + #ifdef ALTQ + ifp->if_altqflags |= ALTQF_READY; + #endif + + ifp->if_timer = 0; + + #if NCARD > 0 + if (alredy_ifatch[is->id_unit] != 1) { + if_attach( ifp ); + alredy_ifatch[is->id_unit] = 1; + } + #else + if_attach(ifp); + #endif + ether_ifattach(ifp); + /* + * Fill the hardware address into ifa_addr if we find an AF_LINK + * entry. We need to do this so bpf's can get the hardware addr of + * this card. netstat likes this too! + */ + ifa = ifp->if_addrlist; + while ((ifa != 0) && (ifa->ifa_addr != 0) && + (ifa->ifa_addr->sa_family != AF_LINK)) + ifa = ifa->ifa_next; + + if ((ifa != 0) && (ifa->ifa_addr != 0)) { + sdl = (struct sockaddr_dl *) ifa->ifa_addr; + sdl->sdl_type = IFT_ETHER; + sdl->sdl_alen = ETHER_ADDR_LEN; + sdl->sdl_slen = 0; + bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN); + } + snstop(is->id_unit); + + #if NBPFILTER > 0 + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); + #endif + + return 1; + } + + + /* + * Reset and initialize the chip + */ + void + sninit(int unit) + { + register struct sn_softc *sc = &sn_softc[unit]; + register struct ifnet *ifp = &sc->arpcom.ac_if; + int s; + int flags; + int mask; + + #if NCARD > 0 + if (sc->gone) + return; + #endif + s = splimp(); + + /* + * This resets the registers mostly to defaults, but doesn't affect + * EEPROM. After the reset cycle, we pause briefly for the chip to + * be happy. + */ + SMC_SELECT_BANK(0); + outw(BASE + RECV_CONTROL_REG_W, RCR_SOFTRESET); + SMC_DELAY(); + outw(BASE + RECV_CONTROL_REG_W, 0x0000); + SMC_DELAY(); + SMC_DELAY(); + + outw(BASE + TXMIT_CONTROL_REG_W, 0x0000); + + /* + * Set the control register to automatically release succesfully + * transmitted packets (making the best use out of our limited + * memory) and to enable the EPH interrupt on certain TX errors. + */ + SMC_SELECT_BANK(1); + outw(BASE + CONTROL_REG_W, (CTR_AUTO_RELEASE | CTR_TE_ENABLE | + CTR_CR_ENABLE | CTR_LE_ENABLE)); + + /* Set squelch level to 240mV (default 480mV) */ + flags = inw(BASE + CONFIG_REG_W); + flags |= CR_SET_SQLCH; + outw(BASE + CONFIG_REG_W, flags); + + /* + * Reset the MMU and wait for it to be un-busy. + */ + SMC_SELECT_BANK(2); + outw(BASE + MMU_CMD_REG_W, MMUCR_RESET); + while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY) /* NOTHING */ + ; + + /* + * Disable all interrupts + */ + outb(BASE + INTR_MASK_REG_B, 0x00); + + sn_setmcast(sc); + + /* + * Set the transmitter control. We want it enabled. + */ + flags = TCR_ENABLE; + + #ifndef SW_PAD + /* + * I (GB) have been unlucky getting this to work. + */ + flags |= TCR_PAD_ENABLE; + #endif /* SW_PAD */ + + outw(BASE + TXMIT_CONTROL_REG_W, flags); + + + /* + * Now, enable interrupts + */ + SMC_SELECT_BANK(2); + + mask = IM_EPH_INT | + IM_RX_OVRN_INT | + IM_RCV_INT | + IM_TX_INT; + + outb(BASE + INTR_MASK_REG_B, mask); + sc->intr_mask = mask; + sc->pages_wanted = -1; + + + /* + * Mark the interface running but not active. + */ + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + /* + * Attempt to push out any waiting packets. + */ + snstart(ifp); + + #ifdef INET6 + in6_ifattach(&sc->arpcom.ac_if, IN6_IFT_802, + (caddr_t)sc->arpcom.ac_enaddr, 0); + #endif /* INET6 */ + + splx(s); + } + + + void + snstart(struct ifnet *ifp) + { + register struct sn_softc *sc = &sn_softc[ifp->if_unit]; + register u_int len; + register struct mbuf *m; + struct mbuf *top; + int s, pad; + int mask; + u_short length; + u_short numPages; + u_char packet_no; + int time_out; + + #if NCARD > 0 + if (sc->gone) + return; + #endif + + s = splimp(); + + if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) { + splx(s); + return; + } + if (sc->pages_wanted != -1) { + splx(s); + printf("sn%d: snstart() while memory allocation pending\n", + ifp->if_unit); + return; + } + startagain: + + /* + * Sneak a peek at the next packet + */ + #ifdef ALTQ + if(ALTQ_IS_ON(ifp)) + m = (*ifp->if_altqdequeue)(ifp, ALTDQ_PEEK); + else + #endif + m = sc->arpcom.ac_if.if_snd.ifq_head; + if (m == 0) { + splx(s); + return; + } + /* + * Compute the frame length and set pad to give an overall even + * number of bytes. Below we assume that the packet length is even. + */ + for (len = 0, top = m; m; m = m->m_next) + len += m->m_len; + + pad = (len & 1); + + /* + * We drop packets that are too large. Perhaps we should truncate + * them instead? + */ + if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) { + + printf("sn%d: large packet discarded (A)\n", ifp->if_unit); + + ++sc->arpcom.ac_if.if_oerrors; + #ifdef ALTQ + if (ALTQ_IS_ON(ifp)){ + m = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE); + if (m != top) + panic("snstart: different mbuf dequeued!"); + }else + #endif + IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m); + m_freem(m); + goto readcheck; + } + #ifdef SW_PAD + + /* + * If HW padding is not turned on, then pad to ETHER_MIN_LEN. + */ + if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) + pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len; + + #endif /* SW_PAD */ + + length = pad + len; + + /* + * The MMU wants the number of pages to be the number of 256 byte + * 'pages', minus 1 (A packet can't ever have 0 pages. We also + * include space for the status word, byte count and control bytes in + * the allocation request. + */ + numPages = (length + 6) >> 8; + + + /* + * Now, try to allocate the memory + */ + SMC_SELECT_BANK(2); + outw(BASE + MMU_CMD_REG_W, MMUCR_ALLOC | numPages); + + /* + * Wait a short amount of time to see if the allocation request + * completes. Otherwise, I enable the interrupt and wait for + * completion asyncronously. + */ + + time_out = MEMORY_WAIT_TIME; + do { + if (inb(BASE + INTR_STAT_REG_B) & IM_ALLOC_INT) + break; + } while (--time_out); + + if (!time_out) { + + /* + * No memory now. Oh well, wait until the chip finds memory + * later. Remember how many pages we were asking for and + * enable the allocation completion interrupt. Also set a + * watchdog in case we miss the interrupt. We mark the + * interface active since there is no point in attempting an + * snstart() until after the memory is available. + */ + mask = inb(BASE + INTR_MASK_REG_B) | IM_ALLOC_INT; + outb(BASE + INTR_MASK_REG_B, mask); + sc->intr_mask = mask; + + sc->arpcom.ac_if.if_timer = 1; + sc->arpcom.ac_if.if_flags |= IFF_OACTIVE; + sc->pages_wanted = numPages; + + splx(s); + return; + } + /* + * The memory allocation completed. Check the results. + */ + packet_no = inb(BASE + ALLOC_RESULT_REG_B); + if (packet_no & ARR_FAILED) { + printf("sn%d: Memory allocation failed\n", ifp->if_unit); + goto startagain; + } + /* + * We have a packet number, so tell the card to use it. + */ + outb(BASE + PACKET_NUM_REG_B, packet_no); + + /* + * Point to the beginning of the packet + */ + outw(BASE + POINTER_REG_W, PTR_AUTOINC | 0x0000); + + /* + * Send the packet length (+6 for status, length and control byte) + * and the status word (set to zeros) + */ + outw(BASE + DATA_REG_W, 0); + outb(BASE + DATA_REG_B, (length + 6) & 0xFF); + outb(BASE + DATA_REG_B, (length + 6) >> 8); + + /* + * Get the packet from the kernel. This will include the Ethernet + * frame header, MAC Addresses etc. + */ + #ifdef ALTQ + if(ALTQ_IS_ON(ifp)){ + m = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE); + if(m != top) + panic("snstart: different mbuf dequeued!"); + }else + #endif + IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m); + + /* + * Push out the data to the card. + */ + for (top = m; m != 0; m = m->m_next) { + + /* + * Push out words. + */ + outsw(BASE + DATA_REG_W, mtod(m, caddr_t), m->m_len / 2); + + /* + * Push out remaining byte. + */ + if (m->m_len & 1) + outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1)); + } + + /* + * Push out padding. + */ + while (pad > 1) { + outw(BASE + DATA_REG_W, 0); + pad -= 2; + } + if (pad) + outb(BASE + DATA_REG_B, 0); + + /* + * Push out control byte and unused packet byte The control byte is 0 + * meaning the packet is even lengthed and no special CRC handling is + * desired. + */ + outw(BASE + DATA_REG_W, 0); + + /* + * Enable the interrupts and let the chipset deal with it Also set a + * watchdog in case we miss the interrupt. + */ + mask = inb(BASE + INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT); + outb(BASE + INTR_MASK_REG_B, mask); + sc->intr_mask = mask; + + outw(BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE); + + sc->arpcom.ac_if.if_flags |= IFF_OACTIVE; + sc->arpcom.ac_if.if_timer = 1; + + #if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_mtap(ifp, top); + } + #endif + + sc->arpcom.ac_if.if_opackets++; + m_freem(top); + + + readcheck: + + /* + * Is another packet coming in? We don't want to overflow the tiny + * RX FIFO. If nothing has arrived then attempt to queue another + * transmit packet. + */ + if (inw(BASE + FIFO_PORTS_REG_W) & FIFO_REMPTY) + goto startagain; + + splx(s); + return; + } + + + + /* Resume a packet transmit operation after a memory allocation + * has completed. + * + * This is basically a hacked up copy of snstart() which handles + * a completed memory allocation the same way snstart() does. + * It then passes control to snstart to handle any other queued + * packets. + */ + static void + snresume(struct ifnet *ifp) + { + register struct sn_softc *sc = &sn_softc[ifp->if_unit]; + register u_int len; + register struct mbuf *m; + struct mbuf *top; + int pad; + int mask; + u_short length; + u_short numPages; + u_short pages_wanted; + u_char packet_no; + + if (sc->pages_wanted < 0) + return; + + pages_wanted = sc->pages_wanted; + sc->pages_wanted = -1; + + /* + * Sneak a peek at the next packet + */ + m = sc->arpcom.ac_if.if_snd.ifq_head; + if (m == 0) { + printf("sn%d: snresume() with nothing to send\n", ifp->if_unit); + return; + } + /* + * Compute the frame length and set pad to give an overall even + * number of bytes. Below we assume that the packet length is even. + */ + for (len = 0, top = m; m; m = m->m_next) + len += m->m_len; + + pad = (len & 1); + + /* + * We drop packets that are too large. Perhaps we should truncate + * them instead? + */ + if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) { + + printf("sn%d: large packet discarded (B)\n", ifp->if_unit); + + ++sc->arpcom.ac_if.if_oerrors; + IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m); + m_freem(m); + return; + } + #ifdef SW_PAD + + /* + * If HW padding is not turned on, then pad to ETHER_MIN_LEN. + */ + if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) + pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len; + + #endif /* SW_PAD */ + + length = pad + len; + + + /* + * The MMU wants the number of pages to be the number of 256 byte + * 'pages', minus 1 (A packet can't ever have 0 pages. We also + * include space for the status word, byte count and control bytes in + * the allocation request. + */ + numPages = (length + 6) >> 8; + + + SMC_SELECT_BANK(2); + + /* + * The memory allocation completed. Check the results. If it failed, + * we simply set a watchdog timer and hope for the best. + */ + packet_no = inb(BASE + ALLOC_RESULT_REG_B); + if (packet_no & ARR_FAILED) { + + printf("sn%d: Memory allocation failed. Weird.\n", ifp->if_unit); + + sc->arpcom.ac_if.if_timer = 1; + + goto try_start; + return; + } + /* + * We have a packet number, so tell the card to use it. + */ + outb(BASE + PACKET_NUM_REG_B, packet_no); + + /* + * Now, numPages should match the pages_wanted recorded when the + * memory allocation was initiated. + */ + if (pages_wanted != numPages) { + + printf("sn%d: memory allocation wrong size. Weird.\n", ifp->if_unit); + + /* + * If the allocation was the wrong size we simply release the + * memory once it is granted. Wait for the MMU to be un-busy. + */ + while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY) /* NOTHING */ + ; + outw(BASE + MMU_CMD_REG_W, MMUCR_FREEPKT); + + return; + } + /* + * Point to the beginning of the packet + */ + outw(BASE + POINTER_REG_W, PTR_AUTOINC | 0x0000); + + /* + * Send the packet length (+6 for status, length and control byte) + * and the status word (set to zeros) + */ + outw(BASE + DATA_REG_W, 0); + outb(BASE + DATA_REG_B, (length + 6) & 0xFF); + outb(BASE + DATA_REG_B, (length + 6) >> 8); + + /* + * Get the packet from the kernel. This will include the Ethernet + * frame header, MAC Addresses etc. + */ + IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m); + + /* + * Push out the data to the card. + */ + for (top = m; m != 0; m = m->m_next) { + + /* + * Push out words. + */ + outsw(BASE + DATA_REG_W, mtod(m, caddr_t), m->m_len / 2); + + /* + * Push out remaining byte. + */ + if (m->m_len & 1) + outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1)); + } + + /* + * Push out padding. + */ + while (pad > 1) { + outw(BASE + DATA_REG_W, 0); + pad -= 2; + } + if (pad) + outb(BASE + DATA_REG_B, 0); + + /* + * Push out control byte and unused packet byte The control byte is 0 + * meaning the packet is even lengthed and no special CRC handling is + * desired. + */ + outw(BASE + DATA_REG_W, 0); + + /* + * Enable the interrupts and let the chipset deal with it Also set a + * watchdog in case we miss the interrupt. + */ + mask = inb(BASE + INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT); + outb(BASE + INTR_MASK_REG_B, mask); + sc->intr_mask = mask; + outw(BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE); + + #if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_mtap(ifp, top); + } + #endif + + sc->arpcom.ac_if.if_opackets++; + m_freem(top); + + try_start: + + /* + * Now pass control to snstart() to queue any additional packets + */ + sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + snstart(ifp); + + /* + * We've sent something, so we're active. Set a watchdog in case the + * TX_EMPTY interrupt is lost. + */ + sc->arpcom.ac_if.if_flags |= IFF_OACTIVE; + sc->arpcom.ac_if.if_timer = 1; + + return; + } + + + void + snintr(int unit) + { + int status, interrupts; + register struct sn_softc *sc = &sn_softc[unit]; + struct ifnet *ifp = &sc->arpcom.ac_if; + int x; + + /* + * Chip state registers + */ + u_char mask; + u_char packet_no; + u_short tx_status; + u_short card_stats; + + #if NCARD > 0 + if (sc->gone) + return; + #endif + + /* + * if_ep.c did this, so I do too. Yet if_ed.c doesn't. I wonder... + */ + x = splbio(); + + /* + * Clear the watchdog. + */ + ifp->if_timer = 0; + + SMC_SELECT_BANK(2); + + /* + * Obtain the current interrupt mask and clear the hardware mask + * while servicing interrupts. + */ + mask = inb(BASE + INTR_MASK_REG_B); + outb(BASE + INTR_MASK_REG_B, 0x00); + + /* + * Get the set of interrupts which occurred and eliminate any which + * are masked. + */ + interrupts = inb(BASE + INTR_STAT_REG_B); + status = interrupts & mask; + + /* + * Now, process each of the interrupt types. + */ + + /* + * Receive Overrun. + */ + if (status & IM_RX_OVRN_INT) { + + /* + * Acknowlege Interrupt + */ + SMC_SELECT_BANK(2); + outb(BASE + INTR_ACK_REG_B, IM_RX_OVRN_INT); + + ++sc->arpcom.ac_if.if_ierrors; + } + /* + * Got a packet. + */ + if (status & IM_RCV_INT) { + #if 1 + int packet_number; + + SMC_SELECT_BANK(2); + packet_number = inw(BASE + FIFO_PORTS_REG_W); + + if (packet_number & FIFO_REMPTY) { + + /* + * we got called , but nothing was on the FIFO + */ + printf("sn: Receive interrupt with nothing on FIFO\n"); + + goto out; + } + #endif + snread(ifp); + } + /* + * An on-card memory allocation came through. + */ + if (status & IM_ALLOC_INT) { + + /* + * Disable this interrupt. + */ + mask &= ~IM_ALLOC_INT; + sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + snresume(&sc->arpcom.ac_if); + } + /* + * TX Completion. Handle a transmit error message. This will only be + * called when there is an error, because of the AUTO_RELEASE mode. + */ + if (status & IM_TX_INT) { + + /* + * Acknowlege Interrupt + */ + SMC_SELECT_BANK(2); + outb(BASE + INTR_ACK_REG_B, IM_TX_INT); + + packet_no = inw(BASE + FIFO_PORTS_REG_W); + packet_no &= FIFO_TX_MASK; + + /* + * select this as the packet to read from + */ + outb(BASE + PACKET_NUM_REG_B, packet_no); + + /* + * Position the pointer to the first word from this packet + */ + outw(BASE + POINTER_REG_W, PTR_AUTOINC | PTR_READ | 0x0000); + + /* + * Fetch the TX status word. The value found here will be a + * copy of the EPH_STATUS_REG_W at the time the transmit + * failed. + */ + tx_status = inw(BASE + DATA_REG_W); + + if (tx_status & EPHSR_TX_SUC) { + printf("sn%d: Successful packet caused interrupt\n", unit); + } else { + ++sc->arpcom.ac_if.if_oerrors; + } + + if (tx_status & EPHSR_LATCOL) + ++sc->arpcom.ac_if.if_collisions; + + /* + * Some of these errors will have disabled transmit. + * Re-enable transmit now. + */ + SMC_SELECT_BANK(0); + + #ifdef SW_PAD + outw(BASE + TXMIT_CONTROL_REG_W, TCR_ENABLE); + #else + outw(BASE + TXMIT_CONTROL_REG_W, TCR_ENABLE | TCR_PAD_ENABLE); + #endif /* SW_PAD */ + + /* + * kill the failed packet. Wait for the MMU to be un-busy. + */ + SMC_SELECT_BANK(2); + while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY) /* NOTHING */ + ; + outw(BASE + MMU_CMD_REG_W, MMUCR_FREEPKT); + + /* + * Attempt to queue more transmits. + */ + sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + snstart(&sc->arpcom.ac_if); + } + /* + * Transmit underrun. We use this opportunity to update transmit + * statistics from the card. + */ + if (status & IM_TX_EMPTY_INT) { + + /* + * Acknowlege Interrupt + */ + SMC_SELECT_BANK(2); + outb(BASE + INTR_ACK_REG_B, IM_TX_EMPTY_INT); + + /* + * Disable this interrupt. + */ + mask &= ~IM_TX_EMPTY_INT; + + SMC_SELECT_BANK(0); + card_stats = inw(BASE + COUNTER_REG_W); + + /* + * Single collisions + */ + sc->arpcom.ac_if.if_collisions += card_stats & ECR_COLN_MASK; + + /* + * Multiple collisions + */ + sc->arpcom.ac_if.if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4; + + SMC_SELECT_BANK(2); + + /* + * Attempt to enqueue some more stuff. + */ + sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + snstart(&sc->arpcom.ac_if); + } + /* + * Some other error. Try to fix it by resetting the adapter. + */ + if (status & IM_EPH_INT) { + snstop(unit); + sninit(unit); + } + + out: + /* + * Handled all interrupt sources. + */ + + SMC_SELECT_BANK(2); + + /* + * Reestablish interrupts from mask which have not been deselected + * during this interrupt. Note that the hardware mask, which was set + * to 0x00 at the start of this service routine, may have been + * updated by one or more of the interrupt handers and we must let + * those new interrupts stay enabled here. + */ + mask |= inb(BASE + INTR_MASK_REG_B); + outb(BASE + INTR_MASK_REG_B, mask); + sc->intr_mask = mask; + + splx(x); + } + + void + snread(register struct ifnet *ifp) + { + struct sn_softc *sc = &sn_softc[ifp->if_unit]; + struct ether_header *eh; + struct mbuf *m; + short status; + int packet_number; + u_short packet_length; + u_char *data; + + SMC_SELECT_BANK(2); + #if 0 + packet_number = inw(BASE + FIFO_PORTS_REG_W); + + if (packet_number & FIFO_REMPTY) { + + /* + * we got called , but nothing was on the FIFO + */ + printf("sn: Receive interrupt with nothing on FIFO\n"); + return; + } + #endif + read_another: + + /* + * Start reading from the start of the packet. Since PTR_RCV is set, + * packet number is found in FIFO_PORTS_REG_W, FIFO_RX_MASK. + */ + outw(BASE + POINTER_REG_W, PTR_READ | PTR_RCV | PTR_AUTOINC | 0x0000); + + /* + * First two words are status and packet_length + */ + status = inw(BASE + DATA_REG_W); + packet_length = inw(BASE + DATA_REG_W) & RLEN_MASK; + + /* + * The packet length contains 3 extra words: status, length, and a + * extra word with the control byte. + */ + packet_length -= 6; + + /* + * Account for receive errors and discard. + */ + if (status & RS_ERRORS) { + ++sc->arpcom.ac_if.if_ierrors; + goto out; + } + /* + * A packet is received. + */ + + /* + * Adjust for odd-length packet. + */ + if (status & RS_ODDFRAME) + packet_length++; + + /* + * Allocate a header mbuf from the kernel. + */ + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) + goto out; + + m->m_pkthdr.rcvif = &sc->arpcom.ac_if; + m->m_pkthdr.len = m->m_len = packet_length; + + /* + * Attach an mbuf cluster + */ + MCLGET(m, M_DONTWAIT); + + /* + * Insist on getting a cluster + */ + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + ++sc->arpcom.ac_if.if_ierrors; + printf("sn: snread() kernel memory allocation problem\n"); + goto out; + } + eh = mtod(m, struct ether_header *); + + /* + * Get packet, including link layer address, from interface. + */ + + data = (u_char *) eh; + insw(BASE + DATA_REG_W, data, packet_length >> 1); + if (packet_length & 1) { + data += packet_length & ~1; + *data = inb(BASE + DATA_REG_B); + } + ++sc->arpcom.ac_if.if_ipackets; + + #if NBPFILTER > 0 + if (sc->arpcom.ac_if.if_bpf) + { + bpf_mtap(&sc->arpcom.ac_if, m); + + /* + * Note that the interface cannot be in promiscuous mode if + * there are no BPF listeners. And if we are in promiscuous + * mode, we have to check if this packet is really ours. + */ + if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) && + (eh->ether_dhost[0] & 1) == 0 && + bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0 && + bcmp(eh->ether_dhost, etherbroadcastaddr, + sizeof(eh->ether_dhost)) != 0) { + m_freem(m); + goto out; + } + } + #endif + + /* + * Remove link layer addresses and whatnot. + */ + m->m_pkthdr.len = m->m_len = packet_length - sizeof(struct ether_header); + m->m_data += sizeof(struct ether_header); + + ether_input(&sc->arpcom.ac_if, eh, m); + + out: + + /* + * Error or good, tell the card to get rid of this packet Wait for + * the MMU to be un-busy. + */ + SMC_SELECT_BANK(2); + while (inw(BASE + MMU_CMD_REG_W) & MMUCR_BUSY) /* NOTHING */ + ; + outw(BASE + MMU_CMD_REG_W, MMUCR_RELEASE); + + /* + * Check whether another packet is ready + */ + packet_number = inw(BASE + FIFO_PORTS_REG_W); + if (packet_number & FIFO_REMPTY) { + return; + } + goto read_another; + } + + + /* + * Handle IOCTLS. This function is completely stolen from if_ep.c + * As with its progenitor, it does not handle hardware address + * changes. + */ + static int + snioctl(register struct ifnet *ifp, int cmd, caddr_t data) + { + register struct ifaddr *ifa = (struct ifaddr *) data; + struct sn_softc *sc = &sn_softc[ifp->if_unit]; + struct ifreq *ifr = (struct ifreq *) data; + int s, error = 0; + + #if NCARD > 0 + if (sc->gone) { + ifp->if_flags &= ~IFF_RUNNING; + return ENXIO; + } + #endif + + s = splimp(); + + switch (cmd) { + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + switch (ifa->ifa_addr->sa_family) { + #ifdef INET + case AF_INET: + sninit(ifp->if_unit); /* before arpwhohas */ + arp_ifinit((struct arpcom *) ifp, ifa); + break; + #endif + #ifdef IPX + case AF_IPX: + { + register struct ipx_addr *ina = &IA_SIPX(ifa)->sipx_addr; + + if (ipx_nullhost(*ina)) + ina->x_host = + *(union ipx_host *) (sc->sc_arpcom.ac_enaddr); + else { + ifp->if_flags &= ~IFF_RUNNING; + bcopy((caddr_t) ina->x_host.c_host, + (caddr_t) sc->sc_arpcom.ac_enaddr, + sizeof(sc->sc_arpcom.ac_enaddr)); + } + /* Set new address. */ + sninit(sc); + break; + } + #endif + #ifdef NS + case AF_NS: + { + register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); + + if (ns_nullhost(*ina)) + ina->x_host = + *(union ns_host *) (sc->arpcom.ac_enaddr); + sn else { + ifp->if_flags &= ~IFF_RUNNING; + bcopy((caddr_t) ina->x_host.c_host, + (caddr_t) sc->arpcom.ac_enaddr, + sizeof(sc->arpcom.ac_enaddr)); + } + sninit(ifp->if_unit); + break; + } + #endif + default: + sninit(ifp->if_unit); + break; + } + break; + case SIOCGIFADDR: + { + struct sockaddr *sa; + + sa = (struct sockaddr *) & ifr->ifr_data; + bcopy((caddr_t) sc->arpcom.ac_enaddr, + (caddr_t) sa->sa_data, ETHER_ADDR_LEN); + } + break; + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { + ifp->if_flags &= ~IFF_RUNNING; + snstop(ifp->if_unit); + break; + } else { + /* reinitialize card on any parameter change */ + sninit(ifp->if_unit); + break; + } + break; + + #ifdef notdef + case SIOCGHWADDR: + bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data, + sizeof(sc->sc_addr)); + break; + #endif + + case SIOCSIFMTU: + + /* + * Set the interface MTU. + */ + if (ifr->ifr_mtu > ETHERMTU) { + error = EINVAL; + } else { + ifp->if_mtu = ifr->ifr_mtu; + } + break; + case SIOCADDMULTI: + error = ether_addmulti(ifr, &sc->arpcom); + if (error == ENETRESET) { + /* update multicast filter list. */ + sn_setmcast(sc); + error = 0; + } + break; + case SIOCDELMULTI: + error = ether_delmulti(ifr, &sc->arpcom); + if (error == ENETRESET) { + /* update multicast filter list. */ + sn_setmcast(sc); + error = 0; + } + break; + default: + error = EINVAL; + } + + splx(s); + + return (error); + } + + void + snreset(int unit) + { + int s; + struct sn_softc *sc = &sn_softc[unit]; + + #if NCARD > 0 + if (sc->gone) + return; + #endif + s = splimp(); + snstop(unit); + sninit(unit); + + splx(s); + } + + void + snwatchdog(struct ifnet *ifp) + { + int s; + struct sn_softc *sc = &sn_softc[ifp->if_unit]; + + #if NCARD > 0 + if (sc->gone) + return; + #endif + s = splimp(); + snintr(ifp->if_unit); + splx(s); + } + + + /* 1. zero the interrupt mask + * 2. clear the enable receive flag + * 3. clear the enable xmit flags + */ + void + snstop(int unit) + { + struct sn_softc *sc = &sn_softc[unit]; + struct ifnet *ifp = &sc->arpcom.ac_if; + + #if NCARD > 0 + if (sc->gone) + return; + #endif + /* + * Clear interrupt mask; disable all interrupts. + */ + SMC_SELECT_BANK(2); + outb(BASE + INTR_MASK_REG_B, 0x00); + + /* + * Disable transmitter and Receiver + */ + SMC_SELECT_BANK(0); + outw(BASE + RECV_CONTROL_REG_W, 0x0000); + outw(BASE + TXMIT_CONTROL_REG_W, 0x0000); + + /* + * Cancel watchdog. + */ + ifp->if_timer = 0; + } + + + + /* + * Function: smc_probe( int ioaddr, int pccard ) + * + * Purpose: + * Tests to see if a given ioaddr points to an SMC9xxx chip. + * Tries to cause as little damage as possible if it's not a SMC chip. + * Returns a 0 on success + * + * Algorithm: + * (1) see if the high byte of BANK_SELECT is 0x33 + * (2) compare the ioaddr with the base register's address + * (3) see if I recognize the chip ID in the appropriate register + * + * + */ + static int + smc_probe(int ioaddr, int pccard) + { + u_int bank; + u_short revision_register; + u_short base_address_register; + + /* + * First, see if the high byte is 0x33 + */ + bank = inw(ioaddr + BANK_SELECT_REG_W); + if ((bank & BSR_DETECT_MASK) != BSR_DETECT_VALUE) { + #ifdef SN_DEBUG + printf("test1 failed\n"); + #endif + return -ENODEV; + } + /* + * The above MIGHT indicate a device, but I need to write to further + * test this. Go to bank 0, then test that the register still + * reports the high byte is 0x33. + */ + outw(ioaddr + BANK_SELECT_REG_W, 0x0000); + bank = inw(ioaddr + BANK_SELECT_REG_W); + if ((bank & BSR_DETECT_MASK) != BSR_DETECT_VALUE) { + #ifdef SN_DEBUG + printf("test2 failed\n"); + #endif + return -ENODEV; + } + /* + * well, we've already written once, so hopefully another time won't + * hurt. This time, I need to switch the bank register to bank 1, so + * I can access the base address register. The contents of the + * BASE_ADDR_REG_W register, after some jiggery pokery, is expected + * to match the I/O port address where the adapter is being probed. + */ + outw(ioaddr + BANK_SELECT_REG_W, 0x0001); + base_address_register = inw(ioaddr + BASE_ADDR_REG_W); + + /* + * This test is nonsence on PC-card architecture, so if + * pccard == 1, skip this test. (hosokawa) + */ + if (!pccard && (ioaddr != (base_address_register >> 3 & 0x3E0))) { + + /* + * Well, the base address register didn't match. Must not + * have been a SMC chip after all. + */ + /* + * printf("sn: ioaddr %x doesn't match card configuration + * (%x)\n", ioaddr, base_address_register >> 3 & 0x3E0 ); + */ + + #ifdef SN_DEBUG + printf("test3 failed ioaddr = 0x%x, base_address_register = 0x%x\n", + ioaddr, base_address_register >> 3 & 0x3E0); + #endif + return -ENODEV; + } + /* + * Check if the revision register is something that I recognize. + * These might need to be added to later, as future revisions could + * be added. + */ + outw(ioaddr + BANK_SELECT_REG_W, 0x3); + revision_register = inw(ioaddr + REVISION_REG_W); + if (!chip_ids[(revision_register >> 4) & 0xF]) { + + /* + * I don't regonize this chip, so... + */ + /* + * printf("sn: ioaddr %x unrecognized revision register: + * %x\n", ioaddr, revision_register ); + */ + + #ifdef SN_DEBUG + printf("test4 failed\n"); + #endif + return -ENODEV; + } + /* + * at this point I'll assume that the chip is an SMC9xxx. It might be + * prudent to check a listing of MAC addresses against the hardware + * address, or do some other tests. + */ + return 0; + } + + #define MCFSZ 8 + + static void + sn_setmcast(struct sn_softc *sc) + { + struct ifnet *ifp = (struct ifnet *)sc; + int flags; + /* + * Set the receiver filter. We want receive enabled and auto strip + * of CRC from received packet. If we are promiscuous then set that + * bit too. + */ + flags = RCR_ENABLE | RCR_STRIP_CRC; + + if (ifp->if_flags & IFF_PROMISC) { + flags |= RCR_PROMISC | RCR_ALMUL; + } else if (ifp->if_flags & IFF_ALLMULTI) { + flags |= RCR_ALMUL; + } else { + u_char mcf[MCFSZ]; + if (sn_getmcf(&sc->arpcom, mcf)) { + /* set filter */ + SMC_SELECT_BANK(3); + outw(BASE + MULTICAST1_REG_W, + ((u_short)mcf[1] << 8) | mcf[0]); + outw(BASE + MULTICAST2_REG_W, + ((u_short)mcf[3] << 8) | mcf[2]); + outw(BASE + MULTICAST3_REG_W, + ((u_short)mcf[5] << 8) | mcf[4]); + outw(BASE + MULTICAST4_REG_W, + ((u_short)mcf[7] << 8) | mcf[6]); + } else { + flags |= RCR_ALMUL; + } + } + SMC_SELECT_BANK(0); + outw(BASE + RECV_CONTROL_REG_W, flags); + } + + static int + sn_getmcf(struct arpcom *ac, u_char *mcf) + { + int i; + struct ether_multi *enm; + struct ether_multistep step; + u_int a, b; + + bzero(mcf, MCFSZ); + ETHER_FIRST_MULTI(step, ac, enm); + while (enm) { + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { + /* impossible to hash */ + bzero(mcf, MCFSZ); + return 0; + } + a = smc_crc(enm->enm_addrlo) & 0x3f; + b = 0; + for (i=0; i < 6; i++) { + b <<= 1; + b |= (a & 0x01); + a >>= 1; + } + mcf[b >> 3] |= 1 << (b & 7); + ETHER_NEXT_MULTI(step, enm); + } + return 1; /* use multicast filter */ + } + + static u_int + smc_crc(u_char *s) + { + int perByte; + int perBit; + const u_int poly = 0xedb88320; + u_int v = 0xffffffff; + u_char c; + + for (perByte = 0; perByte < ETHER_ADDR_LEN; perByte++) { + c = s[perByte]; + for (perBit = 0; perBit < 8; perBit++) { + v = (v >> 1)^(((v ^ c) & 0x01) ? poly : 0); + c >>= 1; + } + } + return v; + } + #endif Index: PAO/sys/i386/isa/if_snreg.h diff -c /dev/null PAO/sys/i386/isa/if_snreg.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:56 1998 --- PAO/sys/i386/isa/if_snreg.h Sun Dec 6 07:47:24 1998 *************** *** 0 **** --- 1,446 ---- + /* + * Copyright (c) 1996 Gardner Buchanan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Gardner Buchanan. + * 4. The name of Gardner Buchanan may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: if_snreg.h,v 1.1.8.1 1998/12/05 22:47:24 itojun Exp $ + */ + + /* + * This file contains register information and access macros for + * the SMC91xxx chipset. + * + * Information contained in this file was obtained from the SMC91C92 + * and SMC91C94 manuals from SMC. You will need one of these in order + * to make any meaningful changes to this driver. Information about + * obtaining one can be found at http://www.smc.com in the components + * division. + * + * This FreeBSD driver is derived in part from the smc9194 Linux driver + * by Erik Stahlman and is Copyright (C) 1996 by Erik Stahlman. + * It is also derived in part from the FreeBSD ep (3C509) driver which + * is Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights + * reserved. + * + */ + #ifndef _IF_SNREG_H_ + #define _IF_SNREG_H_ + + + /* + * Ethernet software status per interface. The first element MUST + * be the arpcom struct since the address of the arpcom struct is + * used as a backdoor to obtain the address of this whole structure + * in many cases. + */ + struct sn_softc { + struct arpcom arpcom; /* Ethernet common part */ + short sn_io_addr; /* i/o bus address (BASE) */ + int pages_wanted; /* Size of outstanding MMU ALLOC */ + int intr_mask; /* Most recently set interrupt mask */ + #if NCARD > 0 + int gone; + #endif /* NCARD > 0 */ + }; + + + /* + * Wait time for memory to be free. This probably shouldn't be + * tuned that much, as waiting for this means nothing else happens + * in the system + */ + #define MEMORY_WAIT_TIME 1000 + + + /* The SMC91xxx uses 16 I/O ports + */ + #define SMC_IO_EXTENT 16 + + + /* + * A description of the SMC registers is probably in order here, + * although for details, the SMC datasheet is invaluable. + * The data sheet I (GB) am using is "SMC91C92 Single Chip Ethernet + * Controller With RAM", Rev. 12/0/94. Constant definitions I give + * here are loosely based on the mnemonic names given to them in the + * data sheet, but there are many exceptions. + * + * Basically, the chip has 4 banks of registers (0 to 3), which + * are accessed by writing a number into the BANK_SELECT register + * (I also use a SMC_SELECT_BANK macro for this). Registers are + * either Byte or Word sized. My constant definitions end in _B + * or _W as appropriate. + * + * The banks are arranged so that for most purposes, bank 2 is all + * that is needed for normal run time tasks. + */ + + /* + * Bank Select Register. This also doubles as + * a chip identification register. This register + * is mapped at the same position in all banks. + */ + #define BANK_SELECT_REG_W 0x0e + #define BSR_DETECT_MASK 0xff00 + #define BSR_DETECT_VALUE 0x3300 + + + /* BANK 0 + */ + + /* Transmit Control Register controls some aspects of the transmit + * behavior of the Ethernet Protocol Handler. + */ + #define TXMIT_CONTROL_REG_W 0x00 + + #define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */ + #define TCR_LOOP 0x0002 /* Enable internal analogue loopback */ + #define TCR_FORCOL 0x0004 /* Force Collision on next TX */ + #define TCR_PAD_ENABLE 0x0080 /* Pad short packets to 64 bytes */ + #define TCR_NOCRC 0x0100 /* Do not append CRC */ + #define TCR_MON_CSN 0x0400 /* monitors the carrier status */ + #define TCR_FDUPLX 0x0800 /* receive packets sent out */ + #define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */ + #define TCR_EPH_LOOP 0x2000 /* Enable internal digital loopback */ + + + /* Status of the last transmitted frame and instantaneous status of + * the Ethernet Protocol Handler jumbled together. In auto-release + * mode this information is simply discarded after each TX. This info + * is copied to the status word of in-memory packets after transmit + * where relevent statuses can be checked. + */ + #define EPH_STATUS_REG_W 0x02 + + #define EPHSR_TX_SUC 0x0001 /* Transmit was successful */ + #define EPHSR_SNGLCOL 0x0002 /* Single collision occurred */ + #define EPHSR_MULCOL 0x0004 /* Multiple Collisions occurred */ + #define EPHSR_LTX_MULT 0x0008 /* Transmit was a multicast */ + #define EPHSR_16COL 0x0010 /* 16 Collisions occurred, TX disabled */ + #define EPHSR_SQET 0x0020 /* SQE Test failed, TX disabled */ + #define EPHSR_LTX_BRD 0x0040 /* Transmit was a broadcast */ + #define EPHSR_DEFR 0x0080 /* TX deferred due to carrier det. */ + #define EPHSR_LATCOL 0x0200 /* Late collision detected, TX disabled */ + #define EPHSR_LOST_CAR 0x0400 /* Lost carrier sense, TX disabled */ + #define EPHSR_EXC_DEF 0x0800 /* Excessive deferrals in TX >2 MAXETHER + * times */ + #define EPHSR_CTR_ROL 0x1000 /* Some ECR Counter(s) rolled over */ + #define EPHSR_RX_OVRN 0x2000 /* Receiver overrun, packets dropped */ + #define EPHSR_LINK_OK 0x4000 /* Link integrity is OK */ + #define EPHSR_TXUNRN 0x8000 /* Transmit underrun */ + + + /* Receiver Control Register controls some aspects of the receive + * behavior of the Ethernet Protocol Handler. + */ + #define RECV_CONTROL_REG_W 0x04 + + #define RCR_RX_ABORT 0x0001 /* Received huge packet */ + #define RCR_PROMISC 0x0002 /* enable promiscuous mode */ + #define RCR_ALMUL 0x0004 /* receive all multicast packets */ + #define RCR_ENABLE 0x0100 /* IFF this is set, we can recieve packets */ + #define RCR_STRIP_CRC 0x0200 /* strips CRC */ + #define RCR_GAIN_BITS 0x0c00 /* PLL Gain control (for testing) */ + #define RCR_FILT_CAR 0x4000 /* Enable 12 bit carrier filter */ + #define RCR_SOFTRESET 0x8000 /* Resets the EPH logic */ + + + /* TX Statistics counters + */ + #define COUNTER_REG_W 0x06 + + #define ECR_COLN_MASK 0x000f /* Vanilla collisions */ + #define ECR_MCOLN_MASK 0x00f0 /* Multiple collisions */ + #define ECR_DTX_MASK 0x0f00 /* Deferred transmits */ + #define ECR_EXDTX_MASK 0xf000 /* Excessively deferred transmits */ + + /* Memory Information + */ + #define MEM_INFO_REG_W 0x08 + + #define MIR_FREE_MASK 0xff00 /* Free memory pages available */ + #define MIR_TOTAL_MASK 0x00ff /* Total memory pages available */ + + /* Memory Configuration + */ + #define MEM_CFG_REG_W 0x0a + + #define MCR_TXRSV_MASK 0x001f /* Count of pages reserved for transmit */ + + + /* Bank 0, Register 0x0c is unised in the SMC91C92 + */ + + + /* BANK 1 + */ + + /* Adapter configuration + */ + #define CONFIG_REG_W 0x00 + + #define CR_INT_SEL0 0x0002 /* Interrupt selector */ + #define CR_INT_SEL1 0x0004 /* Interrupt selector */ + #define CR_DIS_LINK 0x0040 /* Disable 10BaseT Link Test */ + #define CR_16BIT 0x0080 /* Bus width */ + #define CR_AUI_SELECT 0x0100 /* Use external (AUI) Transceiver */ + #define CR_SET_SQLCH 0x0200 /* Squelch level */ + #define CR_FULL_STEP 0x0400 /* AUI signalling mode */ + #define CR_NOW_WAIT_ST 0x1000 /* Disable bus wait states */ + + /* The contents of this port are used by the adapter + * to decode its I/O address. We use it as a varification + * that the adapter is detected properly when probing. + */ + #define BASE_ADDR_REG_W 0x02 /* The select IO Base addr. */ + + /* These registers hold the Ethernet MAC address. + */ + #define IAR_ADDR0_REG_W 0x04 /* My Ethernet address */ + #define IAR_ADDR1_REG_W 0x06 /* My Ethernet address */ + #define IAR_ADDR2_REG_W 0x08 /* My Ethernet address */ + + /* General purpose register used for talking to the EEPROM. + */ + #define GENERAL_REG_W 0x0a + + /* Control register used for talking to the EEPROM and + * setting some EPH functions. + */ + #define CONTROL_REG_W 0x0c + #define CTR_STORE 0x0001 /* Store something to EEPROM */ + #define CTR_RELOAD 0x0002 /* Read EEPROM into registers */ + #define CTR_EEPROM_SEL 0x0004 /* Select registers for Reload/Store */ + #define CTR_TE_ENABLE 0x0020 /* Enable TX Error detection via EPH_INT */ + #define CTR_CR_ENABLE 0x0040 /* Enable Counter Rollover via EPH_INT */ + #define CTR_LE_ENABLE 0x0080 /* Enable Link Error detection via EPH_INT */ + #define CTR_AUTO_RELEASE 0x0800 /* Enable auto release mode for TX */ + #define CTR_POWERDOWN 0x2000 /* Enter powerdown mode */ + #define CTR_RCV_BAD 0x4000 /* Enable receipt of frames with bad CRC */ + + + /* BANK 2 + */ + + /* Memory Management Unit Control Register + * Controls allocation of memory to receive and + * transmit functions. + */ + #define MMU_CMD_REG_W 0x00 + #define MMUCR_BUSY 0x0001 /* MMU busy performing a release */ + + /* MMU Commands: + */ + #define MMUCR_NOP 0x0000 /* Do nothing */ + #define MMUCR_ALLOC 0x0020 /* Or with number of 256 byte packets - 1 */ + #define MMUCR_RESET 0x0040 /* Reset MMU State */ + #define MMUCR_REMOVE 0x0060 /* Dequeue (but not free) current RX packet */ + #define MMUCR_RELEASE 0x0080 /* Dequeue and free the current RX packet */ + #define MMUCR_FREEPKT 0x00a0 /* Release packet in PNR register */ + #define MMUCR_ENQUEUE 0x00c0 /* Enqueue the packet for transmit */ + #define MMUCR_RESETTX 0x00e0 /* Reset transmit queues */ + + /* Packet Number at TX Area + */ + #define PACKET_NUM_REG_B 0x02 + + /* Packet number resulting from MMUCR_ALLOC + */ + #define ALLOC_RESULT_REG_B 0x03 + #define ARR_FAILED 0x80 + + /* Transmit and receive queue heads + */ + #define FIFO_PORTS_REG_W 0x04 + #define FIFO_REMPTY 0x8000 + #define FIFO_TEMPTY 0x0080 + #define FIFO_RX_MASK 0x7f00 + #define FIFO_TX_MASK 0x007f + + /* The address within the packet for reading/writing. The + * PTR_RCV bit is tricky. When PTR_RCV==1, the packet number + * to be read is found in the FIFO_PORTS_REG_W, FIFO_RX_MASK. + * When PTR_RCV==0, the packet number to be written is found + * in the PACKET_NUM_REG_B. + */ + #define POINTER_REG_W 0x06 + #define PTR_READ 0x2000 /* Intended access mode */ + #define PTR_AUTOINC 0x4000 /* Do auto inc after read/write */ + #define PTR_RCV 0x8000 /* FIFO_RX is packet, otherwise PNR is packet */ + + /* Data I/O register to be used in conjunction with + * The pointer register to read and write data from the + * card. The same register can be used for byte and word + * ops. + */ + #define DATA_REG_W 0x08 + #define DATA_REG_B 0x08 + #define DATA_1_REG_B 0x08 + #define DATA_2_REG_B 0x0a + + /* Sense interrupt status (READ) + */ + #define INTR_STAT_REG_B 0x0c + + /* Acknowledge interrupt sources (WRITE) + */ + #define INTR_ACK_REG_B 0x0c + + /* Interrupt mask. Bit set indicates interrupt allowed. + */ + #define INTR_MASK_REG_B 0x0d + + /* Interrupts + */ + #define IM_RCV_INT 0x01 /* A packet has been received */ + #define IM_TX_INT 0x02 /* Packet TX complete */ + #define IM_TX_EMPTY_INT 0x04 /* No packets left to TX */ + #define IM_ALLOC_INT 0x08 /* Memory allocation completed */ + #define IM_RX_OVRN_INT 0x10 /* Receiver was overrun */ + #define IM_EPH_INT 0x20 /* Misc. EPH conditions (see CONTROL_REG_W) */ + #define IM_ERCV_INT 0x40 /* not on SMC9192 */ + + /* BANK 3 + */ + + /* Multicast subscriptions. + * The multicast handling in the SMC90Cxx is quite complicated. A table + * of multicast address subscriptions is provided and a clever way of + * speeding the search of that table by hashing is implemented in the + * hardware. I have ignored this and simply subscribed to all multicasts + * and let the kernel deal with the results. + */ + #define MULTICAST1_REG_W 0x00 + #define MULTICAST2_REG_W 0x02 + #define MULTICAST3_REG_W 0x04 + #define MULTICAST4_REG_W 0x06 + + /* These registers do not exist on SMC9192, or at least + * are not documented in the SMC91C92 data sheet. + * The REVISION_REG_W register does however seem to work. + */ + #define MGMT_REG_W 0x08 + #define REVISION_REG_W 0x0a /* (hi: chip id low: rev #) */ + #define ERCV_REG_W 0x0c + + /* These are constants expected to be found in the + * chip id register. + */ + #define CHIP_9190 3 + #define CHIP_9194 4 + #define CHIP_9195 5 + #define CHIP_91100 7 + + static const char *chip_ids[15] = { + NULL, NULL, NULL, + /* 3 */ "SMC91C90/91C92", + /* 4 */ "SMC91C94", + /* 5 */ "SMC91C95", + NULL, + /* 7 */ "SMC91C100", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL + }; + + + /* When packets are stuffed into the card or sucked out of the card + * they are set up more or less as follows: + * + * Addr msbyte lsbyte + * 00 SSSSSSSS SSSSSSSS - STATUS-WORD 16 bit TX or RX status + * 02 RRRRR - RESERVED (unused) + * 02 CCC CCCCCCCC - BYTE COUNT (RX: always even, TX: bit 0 ignored) + * 04 DDDDDDDD DDDDDDDD - DESTINATION ADDRESS + * 06 DDDDDDDD DDDDDDDD (48 bit Ethernet MAC Address) + * 08 DDDDDDDD DDDDDDDD + * 0A SSSSSSSS SSSSSSSS - SOURCE ADDRESS + * 0C SSSSSSSS SSSSSSSS (48 bit Ethernet MAC Address) + * 0E SSSSSSSS SSSSSSSS + * 10 PPPPPPPP PPPPPPPP + * .. PPPPPPPP PPPPPPPP + * C-2 CCCCCCCC - CONTROL BYTE + * C-2 PPPPPPPP - Last data byte (If odd length) + * + * The STATUS_WORD is derived from the EPH_STATUS_REG_W register + * during transmit and is composed of another set of bits described + * below during receive. + */ + + + /* Receive status bits. These values are found in the status word + * field of a received packet. For receive packets I use the RS_ODDFRAME + * to detect whether a frame has an extra byte on it. The CTLB_ODD + * bit of the control byte tells the same thing. + */ + #define RS_MULTICAST 0x0001 /* Packet is multicast */ + #define RS_HASH_MASK 0x007e /* Mask of multicast hash value */ + #define RS_TOOSHORT 0x0400 /* Frame was a runt, <64 bytes */ + #define RS_TOOLONG 0x0800 /* Frame was giant, >1518 */ + #define RS_ODDFRAME 0x1000 /* Frame is odd lengthed */ + #define RS_BADCRC 0x2000 /* Frame had CRC error */ + #define RS_ALGNERR 0x8000 /* Frame had alignment error */ + #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) + + #define RLEN_MASK 0x07ff /* Significant length bits in RX length */ + + /* The control byte has the following significant bits. + * For transmit, the CTLB_ODD bit specifies whether an extra byte + * is present in the frame. Bit 0 of the byte count field is + * ignored. I just pad every frame to even length and forget about + * it. + */ + #define CTLB_CRC 0x10 /* Add CRC for this packet (TX only) */ + #define CTLB_ODD 0x20 /* The packet length is ODD */ + + + /* + * I define some macros to make it easier to do somewhat common + * or slightly complicated, repeated tasks. + */ + + /* The base I/O address. + */ + #define BASE (sc->sn_io_addr) + + /* Select a register bank, 0 to 3 + */ + #define SMC_SELECT_BANK(x) { outw( BASE + BANK_SELECT_REG_W, (x) ); } + + /* Define a small delay for the reset + */ + #define SMC_DELAY() { inw( BASE + RECV_CONTROL_REG_W );\ + inw( BASE + RECV_CONTROL_REG_W );\ + inw( BASE + RECV_CONTROL_REG_W ); } + + /* Define flags + */ + + #define SN_FLAGS_PCCARD 0x0001 /* PCMCIA (PC-card) */ + #define SN_FLAGS_XJBT10 0x0002 /* Megahertz XJ-BT10 (PCMCIA) */ + + #endif /* _IF_SNREG_H_ */ Index: PAO/sys/i386/isa/if_wl_i82586.h diff -c /dev/null PAO/sys/i386/isa/if_wl_i82586.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:56 1998 --- PAO/sys/i386/isa/if_wl_i82586.h Sun Dec 6 07:47:26 1998 *************** *** 0 **** --- 1,340 ---- + /* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + /* + * HISTORY + * $Log: if_wl_i82586.h,v $ + * Revision 1.1.8.1 1998/12/05 22:47:26 itojun + * sync with pao227 branch. + * right now, pao228 = r228 + (pao227 - r227) + (bsd-nomads 9735) + * + * confirmed that PAO_ALL is compileable **on 227 system**. need your checks. + * + * Revision 1.1.6.1 1998/07/27 11:27:34 kim + * Hidetoshi Kimura(kim@jp.freebsd.org) + * pao227 First Release under isa directory added files. + * PR: + * Reviewed by: + * Submitted by: + * Obtained from: + * + * Revision 1.1.4.1 1998/04/04 23:24:11 itojun + * PAO for FreeBSD 2.2.6-RELEASE. + * I dunno if it compiles or not... + * + * Submitted by: thasegawa@mta.biglobe.ne.jp + * + * Revision 1.1.2.1 1997/12/11 14:00:16 itojun + * PAO-971210 import. hope this works well... + * + * Obtained from: hosokawa + * + * Revision 2.7 91/05/14 16:24:04 mrt + * Correcting copyright + * + * Revision 2.6 91/02/05 17:17:26 mrt + * Changed to new Mach copyright + * [91/02/01 17:43:29 mrt] + * + * Revision 2.5 90/11/26 14:49:45 rvb + * jsb bet me to XMK34, sigh ... + * [90/11/26 rvb] + * Synched 2.5 & 3.0 at I386q (r1.4.1.5) & XMK35 (r2.5) + * [90/11/15 rvb] + * + * Document error bits in Xmt and Rcv. + * [90/10/08 rvb] + * + * Revision 2.4 90/11/05 14:28:00 rpd + * Document error bits in Xmt and Rcv. + * [90/10/08 rvb] + * + * Revision 2.3 90/08/27 21:59:55 dbg + * Add type definition for ushort. + * [90/07/17 dbg] + * + * Revision 2.2 90/05/03 15:42:29 dbg + * Alter for pure kernel. + * [90/04/18 dbg] + * + * Revision 1.4.1.4 90/07/10 11:43:36 rvb + * Comment some symbolic constants. [kupfer] + * + * Revision 1.4.1.3 90/02/28 15:49:41 rvb + * Fix numerous typo's in Olivetti disclaimer. + * [90/02/28 rvb] + * + * Revision 1.4.1.2 90/01/08 13:31:27 rvb + * Add Olivetti copyright. + * [90/01/08 rvb] + * + * Revision 1.4.1.1 89/11/10 09:49:44 rvb + * Redone by Eugene Kuerner at ORC. + * + * Revision 1.3 89/11/01 11:58:44 eugene + * revised some structures for word or 16bit accesses + * + * + */ + + /* + Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., + Cupertino, California. + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appears in all + copies and that both the copyright notice and this permission notice + appear in supporting documentation, and that the name of Olivetti + not be used in advertising or publicity pertaining to distribution + of the software without specific, written prior permission. + + OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + /* + * Defines for managing the status word of the 82586 cpu. For details see + * the Intel LAN Component User's Manual starting at p. 2-14. + * + */ + + #define SCB_SW_INT 0xf000 + #define SCB_SW_CX 0x8000 /* CU finished w/ int. bit set */ + #define SCB_SW_FR 0x4000 /* RU finished receiving a frame */ + #define SCB_SW_CNA 0x2000 /* CU left active state */ + #define SCB_SW_RNR 0x1000 /* RU left ready state */ + + /* + * Defines for managing the Command Unit Status portion of the 82586 + * System Control Block. + * + */ + + #define SCB_CUS_IDLE 0x0000 + #define SCB_CUS_SUSPND 0x0100 + #define SCB_CUS_ACTV 0x0200 + + /* + * Defines for managing the Receive Unit Status portion of the System + * Control Block. + * + */ + + #define SCB_RUS_IDLE 0x0000 + #define SCB_RUS_SUSPND 0x0010 + #define SCB_RUS_NORESRC 0x0020 + #define SCB_RUS_READY 0x0040 + + /* + * Defines that manage portions of the Command Word in the System Control + * Block of the 82586. Below are the Interrupt Acknowledge Bits and their + * appropriate masks. + * + */ + + #define SCB_ACK_CX 0x8000 + #define SCB_ACK_FR 0x4000 + #define SCB_ACK_CNA 0x2000 + #define SCB_ACK_RNR 0x1000 + + /* + * Defines for managing the Command Unit Control word, and the Receive + * Unit Control word. The software RESET bit is also defined. + * + */ + + #define SCB_CU_STRT 0x0100 + #define SCB_CU_RSUM 0x0200 + #define SCB_CU_SUSPND 0x0300 + #define SCB_CU_ABRT 0x0400 + + #define SCB_RESET 0x0080 + + #define SCB_RU_STRT 0x0010 + #define SCB_RU_RSUM 0x0020 + #define SCB_RU_SUSPND 0x0030 + #define SCB_RU_ABRT 0x0040 + + + /* + * The following define Action Commands for the 82586 chip. + * + */ + + #define AC_NOP 0x00 + #define AC_IASETUP 0x01 + #define AC_CONFIGURE 0x02 + #define AC_MCSETUP 0x03 + #define AC_TRANSMIT 0x04 + #define AC_TDR 0x05 + #define AC_DUMP 0x06 + #define AC_DIAGNOSE 0x07 + + + /* + * Defines for General Format for Action Commands, both Status Words, and + * Command Words. + * + */ + + #define AC_SW_C 0x8000 + #define AC_SW_B 0x4000 + #define AC_SW_OK 0x2000 + #define AC_SW_A 0x1000 + #define TC_CARRIER 0x0400 + #define TC_CLS 0x0200 + #define TC_DMA 0x0100 + #define TC_DEFER 0x0080 + #define TC_SQE 0x0040 + #define TC_COLLISION 0x0020 + #define AC_CW_EL 0x8000 + #define AC_CW_S 0x4000 + #define AC_CW_I 0x2000 + + /* + * Specific defines for the transmit action command. + * + */ + + #define TBD_SW_EOF 0x8000 + #define TBD_SW_COUNT 0x3fff + + /* + * Specific defines for the receive frame actions. + * + */ + + #define RBD_SW_EOF 0x8000 + #define RBD_SW_COUNT 0x3fff + + #define RFD_DONE 0x8000 + #define RFD_BUSY 0x4000 + #define RFD_OK 0x2000 + #define RFD_CRC 0x0800 + #define RFD_ALN 0x0400 + #define RFD_RSC 0x0200 + #define RFD_DMA 0x0100 + #define RFD_SHORT 0x0080 + #define RFD_EOF 0x0040 + #define RFD_EL 0x8000 + #define RFD_SUSP 0x4000 + /* + * 82586 chip specific structure definitions. For details, see the Intel + * LAN Components manual. + * + */ + + + typedef struct { + u_short scp_sysbus; + u_short scp_unused[2]; + u_short scp_iscp; + u_short scp_iscp_base; + } scp_t; + + + typedef struct { + u_short iscp_busy; + u_short iscp_scb_offset; + u_short iscp_scb; + u_short iscp_scb_base; + } iscp_t; + + + typedef struct { + u_short scb_status; + u_short scb_command; + u_short scb_cbl_offset; + u_short scb_rfa_offset; + u_short scb_crcerrs; + u_short scb_alnerrs; + u_short scb_rscerrs; + u_short scb_ovrnerrs; + } scb_t; + + + typedef struct { + u_short tbd_offset; + u_char dest_addr[6]; + u_short length; + } transmit_t; + + + typedef struct { + u_short fifolim_bytecnt; + u_short addrlen_mode; + u_short linprio_interframe; + u_short slot_time; + u_short hardware; + u_short min_frame_len; + } configure_t; + + + typedef struct { + u_short ac_status; + u_short ac_command; + u_short ac_link_offset; + union { + transmit_t transmit; + configure_t configure; + u_char iasetup[6]; + } cmd; + } ac_t; + + + typedef struct { + u_short act_count; + u_short next_tbd_offset; + u_short buffer_addr; + u_short buffer_base; + } tbd_t; + + + typedef struct { + u_short status; + u_short command; + u_short link_offset; + u_short rbd_offset; + u_char destination[6]; + u_char source[6]; + u_short length; + } fd_t; + + + typedef struct { + u_short status; + u_short next_rbd_offset; + u_short buffer_addr; + u_short buffer_base; + u_short size; + } rbd_t; Index: PAO/sys/i386/isa/if_wlp.c diff -c /dev/null PAO/sys/i386/isa/if_wlp.c:1.1.8.1 *** /dev/null Fri Dec 25 10:50:57 1998 --- PAO/sys/i386/isa/if_wlp.c Sun Dec 6 07:47:28 1998 *************** *** 0 **** --- 1,2587 ---- + /*- + * NCR WaveLAN PCMCIA driver. + * + * Copyright 1994, Anders Klemets + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The names of the authors may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + /* + * HISTORY + * $Log: if_wlp.c,v $ + * Revision 1.1.8.1 1998/12/05 22:47:28 itojun + * sync with pao227 branch. + * right now, pao228 = r228 + (pao227 - r227) + (bsd-nomads 9735) + * + * confirmed that PAO_ALL is compileable **on 227 system**. need your checks. + * + * Revision 1.1.6.4 1998/10/14 09:32:29 nakagawa + * - PAO98 main part merge + * - delete NCARD section in scsi_low_if.h (not need) + * + * Reviewed by: nakagawa@jp.FreeBSD.org + * Submitted by: kura@melchior.q.t.u-tokyo.ac.jp + * + * Revision 1.1.6.3 1998/09/03 08:15:32 onoe + * Support SIOCGIFADDR to get hardware address for bpf(4) + * + * Revision 1.1.6.2 1998/09/03 08:06:40 onoe + * delete 2nd argument named 'first' from XXXcrdinit, which is now obsoleted. + * also XXXsuspend was deleted. + * + * Revision 1.1.6.1 1998/07/27 11:27:35 kim + * Hidetoshi Kimura(kim@jp.freebsd.org) + * pao227 First Release under isa directory added files. + * PR: + * Reviewed by: + * Submitted by: + * Obtained from: + * + * Revision 1.1.4.2.2.1 1998/06/25 06:14:01 nakagawa + * merge cbtest980624.diff + * PR: + * Reviewed by: + * Submitted by: + * Obtained from: + * + * Revision 1.1.4.2 1998/05/24 07:49:13 itojun + * catch up to hosokawa's PAO-980430 + * + * Revision 1.1.4.1 1998/04/04 23:24:12 itojun + * PAO for FreeBSD 2.2.6-RELEASE. + * I dunno if it compiles or not... + * + * Submitted by: thasegawa@mta.biglobe.ne.jp + * + * Revision 1.1.2.2 1998/02/19 05:01:53 hosokawa + * PR: + * update my e-mail addresses. + * + * Revision 1.1.2.1 1997/12/11 14:00:17 itojun + * PAO-971210 import. hope this works well... + * + * Obtained from: hosokawa + * + * Revision 1.1 1994/06/02 20:21:27 klemets + * Initial revision + * + * Ported to BSDI by Robert Morris. + * + * Ported to freebsd by Jim Binkley. jrb@cs.pdx.edu, 1/96. + * 1. Emasculated rtm's code for hot-swapping since I don't have + * time to get that going and I expect the freebsd pcmcia + * general code will be arriving soon. + * The assumption here is that wlpprobe simply turns on the + * pcmcia bus in a manner analogous to if_ze.c. + * 2. Added code for BPF and promiscous mode seems to work fine + * on unicast packets for other nodes. Not sure yet about + * different NWIDs. + * 3. #ifdef TIMER looks funky to me. Have tested it a bit + * and modified it to use if_timer, but it isn't ON. + * 4. multicast is ON and seems to work at this point. + * + * config note: + * The irq passed in from the config line is the irq that + * will indeed be used. It should be correct for pcmcia/isa. + * Only: 3,4,5,7,9,10,11,12,14,15 can be used. + * The driver takes what it gets during attach and programs + * the pcmcia card accordingly to map to that ISA irq. + * + * The if_wl driver being a different piece of hardware ignores + * what it gets from config (should check it though) and the irq is + * effectively set by the dos instconf.exe utility in the PSA + * nvram area. + * + * HW note: HW consists logically of the Intel 82593 lan controller + * (on the pc card itself) + the radio modem. There is also a PSA + * or nvram storage area. I run the dos instconf.exe utility to + * set the card up before the driver itself runs under unix. + * + * Working config line on ibm 755 thinkpad and ibm 701c thinkpads: + * + * device wlp0 at isa? port 0x300 net irq 11 iomem 0xd8000 vector wlpintr + * + */ + /* + * PC-card hotplug extention (WL_PCCARD): + * Tatsumi Hosokawa , 1996 + */ + #define WL_PCCARD 1 + + #include "wlp.h" + #include "bpfilter.h" + #include "card.h" + + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #ifdef INET + #include + #include + #include + #include + #include + #endif + + #ifdef NS + #include + #include + #endif + + #if NBPFILTER > 0 + #include + #include + #endif + + #include + #include + + #ifdef PC98 + #include + #else + #include + #endif + #include + #include + + #if 0 + #include + #include + #endif + #include + #include + + #define WLP_NPORT 8 /* 8 8-bit registers */ + #if 0 + typedef int boolean_t; + #endif + #define loutb outsb + #define linb insb + #define TRUE 1 + #define FALSE 0 + + int xtradebug = 0; + + char t_packet[WAVELAN_MTU + WAVELAN_ADDR_SIZE + sizeof(long)]; + static int xmt_watch = 0; + static int gathersnr = 0; + int wlp_overrunning; + + struct wlp_softc{ + struct arpcom arpcom; /* ethernet common */ + #ifdef BSDI + struct device wlp_dev; /* base device */ + struct isadev wlp_id; /* ISA device */ + struct intrhand wlp_ih; /* interrupt vectoring */ + #endif + + u_char nwid[2]; /* shadows radio modem registers */ + int base; /* Address of I/O mapped registers */ + int unit; + caddr_t psa; /* Address of PSA */ + int stop; /* Current 82593 Stop Hit Register */ + int flags; + short mode; + int rfp; /* last DMA machine receive pointer */ + u_char status; + boolean_t seated; + boolean_t tbusy; + boolean_t mmi_inited; + boolean_t cmd_request; + boolean_t cmd_wait; + boolean_t deferred; + boolean_t power_down; + struct i82593_conf_block cfblk; + int band_2400MHz; + #if NBPFILTER > 0 + #if 0 + caddr_t wlp_bpf; + #endif + #endif + #if NCARD > 0 + int gone; + struct wavelan_conf wl_conf; + #endif + } wlp_softc[NWLP]; + + /* globals for wavelan signal strength cache */ + int w_sigitems; /* number of cached entries */ + struct w_sigcache w_sigcache[ MAXCACHEITEMS ]; /* array of cache entries */ + int NextCacheItem; /* index for next cache entry + * and also indicates number + * of cached entries + */ + + int wlpprobe(struct isa_device *); + int wlpattach(struct isa_device *); + struct isa_driver wlpdriver = { + wlpprobe, wlpattach, "wlp", 0 + }; + void wlpintr(int); + static void wlpstart(struct ifnet *); + static void wlpinit(int unit); + void wlprustrt(int unit); + int wlphwrst(int unit); + static void wlpinitmmi(int unit); + int wlpreset(int unit); + void wlpwatch(struct ifnet *b_ptr); + static void wlprcv(int unit); + void wlpxmt(int unit, struct mbuf *m); + int wlpdiag(int unit); + int wlpconfig(int unit); + int wlpcmd(int unit, char *str, int cmd, int result); + u_short wlpmmiread(int base, u_short reg); + static int wlp_start_of_frame(int unit, int rfp); + static void wlp_graceful_shutdown(int unit); + static void wlpgetsnr(int unit, struct ether_header *ehp, u_char siglvl, + u_char sillvl, u_char sigqual); + int wlpioctl(struct ifnet *ifp, int cmd, caddr_t data); + static void wlpsetnwid(int unit, int base, int data); + void wlpdump(int unit); + static + int read_ringbuf(int unit, int addr, char *buf, int len); + #ifdef bsdi + void wlpnotify(struct device *dev); + #endif + static void wlpread(int unit, int fd_p, int len); + static void wl_cache_store(int unit, int base, + struct ether_header *eh, struct mbuf *m); + static int OldestEntryNdx( void ); + + /* diagnostic info */ + struct wl_cntrs wlp_cntrs[NWLP]; + + /* + * Keep interface structures separately so that the rest of the + * kernel network code won't be messed up if the card is taken + * out and the wlp_softc deallocated. Also remember if we've + * ever called if_attach() on each interface, so as to avoid + * doing it again after ejection and re-insertion. + */ + #if 0 + struct arpcom wlp_ac[NWLP]; + #endif + int wlp_ifattached[NWLP]; + + #define WLPSOFTC(unit) ((struct wlp_softc *) &wlp_softc[unit]) + #if 0 + #define WLPIF(unit) (wlp_ac[unit].ac_if) + #define WLPADDR(unit) (wlp_ac[unit].ac_enaddr) + #else + #define WLPIF(unit) (wlp_softc[unit].arpcom.ac_if) + #define WLPADDR(unit) (wlp_softc[unit].arpcom.ac_enaddr) + #endif + + #if NCARD > 0 + #include + #include + #include + #include + + /* + * PC-Card (PCMCIA) specific code. + */ + static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ + static void wlpunload(struct pccard_devinfo *); /* Disable driver */ + static int wlpcrdinit(struct pccard_devinfo *); /* init device */ + + static struct pccard_device wlp_info = { + "wlp", + wlpcrdinit, + wlpunload, + card_intr, + 0, /* Attributes - presently unused */ + &net_imask /* Interrupt mask for device */ + }; + + DATA_SET(pccarddrv_set, wlp_info); + + /* + * Initialize the device - called from Slot manager. + */ + static int + wlpcrdinit(struct pccard_devinfo *devi) + { + struct wlp_softc *sc = &wlp_softc[devi->pd_unit]; + + /* validate unit number. */ + if (devi->pd_unit >= NWLP) + return(ENODEV); + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + sc->gone = 0; + sc->wl_conf = *(struct wavelan_conf *)devi->misc; + #if 0 + if (wlpprobe(&devi->isahd,devi->misc)==0) + return(ENXIO); + #endif + if (wlpattach(&devi->isahd)==0) + return(ENXIO); + return(0); + } + + /* + * wlpunload - unload the driver and clear the table. + * XXX TODO: + * This is usually called when the card is ejected, but + * can be caused by a modunload of a controller driver. + * The idea is to reset the driver's view of the device + * and ensure that any driver entry points such as + * read and write do not hang. + */ + static void + wlpunload(struct pccard_devinfo *devi) + { + struct wlp_softc *sc = &wlp_softc[devi->pd_unit]; + struct ifnet *ifp = &sc->arpcom.ac_if; + + ifp->if_flags &= ~IFF_RUNNING; + if_down(ifp); + sc->gone = 1; + printf("wlp%d: unload\n", devi->pd_unit); + } + + /* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int + card_intr(struct pccard_devinfo *devi) + { + wlpintr(devi->pd_unit); + return(1); + } + #endif /* NCARD > 0 */ + + /* + * wlpprobe: + * + * This function "probes" or checks for the WaveLAN board on the bus to + * see if it is there. It reads the PCMCIA Card Information Structure, + * looking for the level 1 version/product info tuple. It will return + * successfully only if the product information string begins with + * "wavelan". Case is not important. The config code expects to see + * a successful return from the probe routine before attach will be + * called. + * + * input : address device is mapped to, and unit # being checked + * output : a '1' is returned if the board exists, and a 0 otherwise + * + * CALLS: + * pcmcia_card_name(); + * bcmp(); + */ + #ifndef WL_PCCARD + int pcmciaprobe (unsigned int, int); + int pcmciaattach (unsigned int, int); + #endif + + int + wlpprobe(struct isa_device *id) + { + #ifndef WL_PCCARD + unsigned long oldpri; + unsigned char tuplebuf[80], *p; + int len; + int rc; + + extern int pcmcia_slot; + int slot = pcmcia_slot; + char card_name[256]; + #endif /* WL_PCCARD */ + + #ifdef DEBUG + printf("wlpprobe:%d base %x, irq %x, maddr %x\n", unit, base, + id->id_irq, id->id_maddr); + #endif + + #ifndef WL_PCCARD + /* TBD make sure irq/maddr set + */ + rc = pcmciaprobe((unsigned int)id->id_maddr, 0); + if (rc == 0) + return(0); + + pcmciaattach((unsigned int)id->id_maddr, 0); + + if(pcmcia_card_name(slot, card_name, sizeof(card_name)) < 0){ + printf("wlpprobe: cannot get card name\n"); + return(0); + } + + /* note: I have cards with both versions. jrb + */ + #define NAME1 "NCR~WaveLAN/PCMCIA~Version 1.01" + #define NAME0 "NCR~WaveLAN/PCMCIA~Version 1.00" + + if(bcmp(card_name, NAME1, sizeof(NAME1)-1) != 0){ + if(bcmp(card_name, NAME0, sizeof(NAME0)-1) != 0){ + printf("wlpprobe: card name does not match\n"); + printf("got %s\n", card_name); + printf("expected %s\n", NAME0); + return(0); + } + } + #endif /* !WL_PCCARD */ + + #ifdef bsdi + /* sanity check on irq would be useful. set in psa and used + * by device presumably BUT fetching it would be useful + * and comparing against device setup + * TBD. jrb. + * note. irq is id->id_irq, and iobase id->id_iobase + */ + base = ia->ia_iobase; + if (isa_portcheck(base, WLP_NPORT) == 0) { + return (0); + } + + if (ia->ia_irq == IRQUNK) { + if ((ia->ia_irq = isa_irqalloc(PCMCIA_IRQS)) == 0) { + printf("wlp%d: no irq available\n", cf->cf_unit); + return (0); + } + } + + ia->ia_iosize = WLP_NPORT; + #endif + + #ifdef WL_PCCARD + return 0; + #else /* WL_PCCARD */ + return (WLP_NPORT); + #endif /* WL_PCCARD */ + } + + /* + * wlpattach: + * + * This function attaches a WaveLAN board to the "system". The rest of + * runtime structures are initialized here (this routine is called after + * a successful probe of the board). Once the ethernet address is read + * and stored, the board's ifnet structure is attached and readied. + * + * input : isa_dev structure setup in autoconfig + * output : board structs and ifnet is setup + * + * CALLS: + * pcmcia_set_cor(); + * pcic_map_memory(); + * pcic_map_io(); + */ + int + wlpattach(struct isa_device *id) + { + struct wlp_softc *sp = WLPSOFTC(id->id_unit); + int unit = id->id_unit; + int base = id->id_iobase; + int please_init = 0; + register struct ifnet *ifp = &WLPIF(unit); + int i; + int configured; + #ifndef WL_PCCARD + int comp_number, netw_addr; + extern int pcmcia_slot; /* set in if_wlp_pcmcia.c */ + int slot = pcmcia_slot; + char tuplebuf[80], *p; + int len; + #endif + + sp->band_2400MHz = 0; + #ifdef WAVELAN_PCMCIA_24 + sp->band_2400MHz = 1; + #endif /* WAVELAN_PCMCIA_24 */ + if (id->id_flags & WLP_2400MHZ) { + sp->band_2400MHz = 1; + } + sp->unit = unit; + sp->base = base; + sp->seated = 1; + + #ifdef DEBUG + printf("wlpattach%d, base=%x\n", unit, base); + #endif + + #ifdef WL_PCCARD + sp->flags = 0; + sp->mode = 0; + configured = sp->wl_conf.wc_confstat & 1; + sp->nwid[0] = sp->wl_conf.wc_nwid[0]; + sp->nwid[1] = sp->wl_conf.wc_nwid[1]; + for (i = 0; i < 6; i++) { + WLPADDR(unit)[i] = sp->wl_conf.wc_macaddr[i]; + } + printf("wlp%d: nwid [%x:%x] mac:[%x:%x:%x:%x:%x:%x]\n", id->id_unit, + sp->nwid[0], sp->nwid[1], + WLPADDR(unit)[0], WLPADDR(unit)[1], WLPADDR(unit)[2], + WLPADDR(unit)[3], WLPADDR(unit)[4], WLPADDR(unit)[5]); + #else /* WL_PCCARD */ + /* Tell the card it's configured by setting low bit of COR. */ + /* Also does a software reset. */ + if(pcmcia_set_cor(slot, 1) < 0) { + return(0); + } + + /* permanently map attribute memory */ + pcic_map_memory(slot, 0, kvtop((char *)pcmcia_maddr(slot)), 0x0, 0x4000, ATTRIBUTE, 1); + sp->psa = (char *)pcmcia_maddr(slot); + sp->psa += 0xe00; + + /* Permanently map the I/O registers. */ + pcic_map_io(slot, 0, base, WLP_NPORT, 1); + + sp->flags = 0; + sp->mode = 0; + + configured = READ_PSA(PSA_CONF_STATUS) & 1; + sp->nwid[0] = READ_PSA(NETW_ID); + sp->nwid[1] = READ_PSA(NETW_ID+1); + if(configured) { + if(READ_PSA(PSA_MAC_SELECT) & 1) { + netw_addr = NETW_ADDR_LOCAL; + } + else { + netw_addr = NETW_ADDR; /* use factory assigned address */ + } + } + else { + netw_addr = NETW_ADDR; + } + for(i=0; i < WAVELAN_ADDR_SIZE; ++i) { + WLPADDR(unit)[i] = READ_PSA(netw_addr+i); + } + printf("wlp%d: nwid [%x:%x] mac:[%x:%x:%x:%x:%x:%x]\n", id->id_unit, + sp->nwid[0], sp->nwid[1], + WLPADDR(unit)[0], WLPADDR(unit)[1], WLPADDR(unit)[2], + WLPADDR(unit)[3], WLPADDR(unit)[4], WLPADDR(unit)[5]); + comp_number = READ_PSA(PSA_COMP_NUMBER); + if(comp_number & 1) + printf("PC-MC "); + else + if(comp_number & 4) + printf("PCMCIA "); + else + printf("PC-AT "); + if(comp_number & 2) { + switch(READ_PSA(PSA_SUBBAND) & 15) { + case 1: + printf("2425"); + break; + case 2: + printf("2460"); + break; + case 3: + printf("2484"); + break; + case 4: + printf("2430.5"); + break; + default: + printf("???"); + } + } + else { + if (sp->band_2400MHz) { + printf("2400"); + } + else { + printf("915"); + } + } + printf(" MHz\n"); + #endif /* WL_PCCARD */ + + /* turn on the power and check that the modem is connected + before we attempt to access the Modem Management Interface */ + outb(HACR(base), HACR_PWR_STAT); + + if(wlp_ifattached[unit] == 0){ + ifp->if_softc = sp; + ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX; + #ifdef MULTICAST + ifp->if_flags |= IFF_MULTICAST; + #endif + #ifdef DEBUG + ifp->if_flags |= IFF_DEBUG; + #endif + ifp->if_unit = sp->unit; + ifp->if_name = "wlp"; + ifp->if_output = ether_output; + ifp->if_start = wlpstart; + ifp->if_ioctl = wlpioctl; + ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + if_attach(ifp); + ether_ifattach(ifp); + wlp_ifattached[unit] = 1; + + #if NBPFILTER > 0 + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); + #endif + } else { + /* We've already seen this card; just reset it. */ + please_init = 1; + } + + #ifdef bsdi + sp->wlp_ih.ih_fun = wlpintr; + sp->wlp_ih.ih_arg = (void *) sp; + pcmcia_attach_child(parent, self, &sp->wlp_ih, ia, wlpnotify, &wlpcd); + #endif + #ifndef WL_PCCARD + /* tell pcmcia controller to map irq + */ + pcic_map_irq(slot, ffs(id->id_irq) - 1); + #endif /* WL_PCCARD */ + if(please_init) { + wlpinit(unit); + } + return(1); + } + + #ifdef bsdi + /* + * The card has been removed. Soon the wlp_softc structure won't + * be available; stop using it. But the ifnet structure isn't + * part of wlp_softc in this driver, so we can leave it alone. + * Thus when the card is re-inserted, it will start working + * where it left off. + */ + void + wlpnotify(struct device *dev) + { + int unit = dev->dv_unit; + struct wlp_softc *sp = WLPSOFTC(unit); + struct ifnet *ifp = &WLPIF(unit); + + #ifdef DEBUG + if (xtradebug) + printf("wlp%d: wlpnotify()\n", unit); + #endif + + isa_portfree(sp->base, WLP_NPORT); + } + #endif + + /* + * initialize rf-modem + * + * CALLERS: wlphwrst + */ + static void + wlpinitmmi(int unit) + { + struct wlp_softc *sp = WLPSOFTC(unit); + int configured; + #ifdef WL_PCCARD + configured = sp->wl_conf.wc_confstat & 1; + #else /* WL_PCCARD */ + configured = READ_PSA(PSA_CONF_STATUS) & 1; + #endif /* WL_PCCARD */ + + /* Set default modem control parameters. Taken from NCR document + 407-0024326 Rev. A */ + MMI_WRITE(MMC_JABBER_ENABLE, 0x01); + MMI_WRITE(MMC_ANTEN_SEL, 0x02); + MMI_WRITE(MMC_IFS, 0x20); + MMI_WRITE(MMC_MOD_DELAY, 0x04); + MMI_WRITE(MMC_JAM_TIME, 0x38); + MMI_WRITE(MMC_DECAY_PRM, 0x00); /* obsolete ? */ + MMI_WRITE(MMC_DECAY_UPDAT_PRM, 0x00); + if(!configured) { + MMI_WRITE(MMC_LOOPT_SEL, 0x00); + MMI_WRITE(MMC_THR_PRE_SET, 0x03); /* 0x03 for PCMCIA */ + MMI_WRITE(MMC_QUALITY_THR, 0x03); + } + else { + /* use configuration defaults from parameter storage area */ + #ifdef WL_PCCARD + if(sp->wl_conf.wc_netw_id_sel & 1) { + MMI_WRITE(MMC_LOOPT_SEL, 0x00); + } else { + MMI_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */ + } + MMI_WRITE(MMC_THR_PRE_SET, sp->wl_conf.wc_thr_pre_set & 0x3f); + MMI_WRITE(MMC_QUALITY_THR, sp->wl_conf.wc_quality_thr & 0x0f); + #else /* WL_PCCARD */ + if(READ_PSA(PSA_NETW_ID_SELECT) & 1) { + MMI_WRITE(MMC_LOOPT_SEL, 0x00); + } else { + MMI_WRITE(MMC_LOOPT_SEL, 0x40); /* disable network id check */ + } + MMI_WRITE(MMC_THR_PRE_SET, READ_PSA(PSA_THR_PRE_SET) & 0x3f); + MMI_WRITE(MMC_QUALITY_THR, READ_PSA(PSA_QUALITY_THR) & 0x0f); + #endif /* WL_PCCARD */ + } + MMI_WRITE(MMC_FREEZE, 0x00); + MMI_WRITE(MMC_ENCR_ENABLE, 0x00); + + MMI_WRITE(MMC_NETW_ID_L,sp->nwid[1]); /* set NWID */ + MMI_WRITE(MMC_NETW_ID_H,sp->nwid[0]); + + if (sp->band_2400MHz) { + /* + * Start the modem's receive unit on version 2.00 + * frequency select cards. It is based on Joe Finney's + * (joe@comp.lancs.ac.uk) code for Linux. + */ + MMI_WRITE(0x21, 0x0f); + MMI_WRITE(0x20, 0x0e); + DELAY(100000); + MMI_WRITE(0x21, 0x61); + MMI_WRITE(0x20, 0x0e); + DELAY(100000); + } + + sp->mmi_inited = TRUE; + } + + u_short + wlpmmiread(int base, u_short reg) + { + while(inb(HASR(base)) & HASR_MMI_BUSY) ; + outb(MMR(base),reg << 1); + outb(MMD(base),0); /* dummy write */ + while(inb(HASR(base)) & HASR_MMI_BUSY) ; + return (u_short)inb(MMD(base)); + } + + /* + * wlpinit: + * + * Another routine that interfaces the "if" layer to this driver. + * Simply resets the structures that are used by "upper layers". + * As well as calling wlphwrst that does reset the WaveLAN board. + * + * input : board number + * output : structures (if structs) and board are reset + * + */ + static + void + wlpinit(int unit) + { + struct wlp_softc *sp = WLPSOFTC(unit); + struct ifnet *ifp; + int stat; + unsigned long oldpri; + + + #ifdef DEBUG + printf("wlpinit\n"); + #endif + + /* The card might have been ejected. */ + if(sp == 0) + return; + + /* initialize the signal cache + */ + NextCacheItem = 0; + w_sigitems = 0; + + ifp = &WLPIF(unit); + if (ifp->if_addrlist == (struct ifaddr *)0) { + return; + } + #ifdef DEBUG + if (ifp->if_flags & IFF_DEBUG) { + printf("wl%d: entered wlpinit() \n",unit); + } + #endif + if ((stat = wlphwrst(unit)) == TRUE) { + #ifdef TIMER + WLPIF(unit).if_timer = 60; + #endif + oldpri = splimp(); + WLPIF(unit).if_flags |= IFF_RUNNING; + sp->flags |= DSF_RUNNING; + sp->tbusy = FALSE; + WLPIF(unit).if_flags &= ~IFF_OACTIVE; + sp->cmd_request = FALSE; + sp->cmd_wait = FALSE; + sp->deferred = FALSE; + wlpstart(ifp); + splx(oldpri); + } else + printf("wl%d init(): trouble resetting board.\n", unit); + #ifdef DEBUG + printf("END wlpinit\n"); + #endif + } + + /* + * wlphwrst: + * + * This routine resets the WaveLAN board that corresponds to the + * board number passed in. + * + * input : board number to do a hardware reset + * output : board is reset + * + */ + int + wlphwrst(int unit) + { + int i; + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + #ifdef DEBUG + printf("wl%d: entered wlphwrst()\n",unit); + #endif + + /* reset host adapter */ + outb(HACR(base), + HACR_PWR_STAT | HACR_TX_DMA_RESET | HACR_RX_DMA_RESET); + sp->power_down = FALSE; + if(inb(HASR(base)) & HASR_NO_CLK) { + printf("wl%d: modem not connected.\n", unit); + return FALSE; + } + + outb(LCCR(base), OP0_RESET); /* reset the LAN controller */ + DELAY(100000); + + /* initialize modem */ + #ifdef DEBUG + printf("wlpinitmm\n"); + #endif + wlpinitmmi(unit); + #ifdef DEBUG + printf("END wlpinitmm, START wlpconfig\n"); + #endif + + if (wlpconfig(unit) == FALSE) + return(FALSE); + + /* + * insert code for loopback test here + * + */ + #ifdef DEBUG + printf("start wlprustrt\n"); + #endif + wlprustrt(unit); /* start receive unit */ + #ifdef DEBUG + printf("END wlprustrt/wlphwrst()\n"); + #endif + + + return(TRUE); + } + + /* + * wlpstart: + * + * This is yet another interface routine that simply tries to output a + * in a packet after a reset. + * + * input : board number + * output : stuff sent to board if any there + * + */ + static void + wlpstart(struct ifnet *ifp) + { + struct mbuf *m; + int unit = ifp->if_unit; + struct wlp_softc *is = WLPSOFTC(unit); + int base; + + #ifdef DEBUG + if (ifp->if_flags & IFF_DEBUG) { + printf("wl%d: entered wlpstart() qlen %d\n", + unit, ifp->if_snd.ifq_len); + } + #endif + + /* The card might have been ejected. */ + if(is == 0) + return; + + base = is->base; + + /* XXX the following is a debug statement, remove for efficiency */ + #ifdef undef + if(is->cmd_request) { + printf("wlpstart called with cmd_request=%d deferred=%d\n", + is->cmd_request,is->deferred); + } + #endif + if (is->tbusy || is->power_down) + return; + + IF_DEQUEUE(&ifp->if_snd, m); + if (m != (struct mbuf *) 0) + { + is->tbusy = TRUE; + WLPIF(unit).if_flags |= IFF_OACTIVE; + + wlp_cntrs[unit].xmt.xmt++; + ifp->if_opackets++; + #if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_mtap(ifp, m); + } + #endif + wlpxmt(unit, m); + } + + return; + } + + /* return the starting address of the frame pointed to by the + receive frame pointer */ + static int + wlp_start_of_frame(int unit,int rfp) + { + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + int rp, len, len1, len_ptr; + unsigned char c; + + rp = (rfp - 5 + RX_SIZE) % RX_SIZE; + outb(PIORL(base), rp & 0xff); + outb(PIORH(base), ((rp >> 8) & PIORH_MASK)); + len = inb(PIOP(base)); + len |= inb(PIOP(base)) << 8; + + len_ptr = rp; + len_ptr = read_ringbuf(unit, len_ptr, &c, 1); + len1 = c; + len_ptr = read_ringbuf(unit, len_ptr, &c, 1); + len1 |= c << 8; + if(len != len1 || len > 1600) + printf("oops, rfp %d rp %d len 0x%x len1 0x%x\n", rfp, rp, len, len1); + + if(len > 1600) + return(-1); + else + return (rp - len + RX_SIZE) % RX_SIZE; + } + + + /* + * wlprcv: + * + * This routine is called by the interrupt handler to initiate a + * packet transfer from the board to the "if" layer above this + * driver. This routine checks if a buffer has been successfully + * received by the WaveLAN. If so, the routine wlpread is called + * to do the actual transfer of the board data (including the + * ethernet header) into a packet (consisting of an mbuf chain). + * + * input : number of the board to check + * output : if a packet is available, it is "sent up" + * + */ + static void + wlprcv(int unit) + { + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + int newrfp, rp, len, f_start, status; + int i593_rfp, stat_ptr; + unsigned char c; + int sanity; + + #ifdef DEBUG + if (xtradebug) + printf("wl%d: entered wlprcv()\n",unit); + #endif + + /* get the new receive frame pointer from the i82593 chip */ + outb(LCCR(base), CR0_STATUS_2 | OP0_NOP); + i593_rfp = inb(LCSR(base)); + i593_rfp |= inb(LCSR(base)) << 8; + i593_rfp %= RX_SIZE; + + /* Get the new receive frame pointer from the WaveLAN host adapter. + * It is 3 bytes more than te increment of the i82593 receive + * frame pointer, for each packet. + */ + newrfp = inb(RPLL(base)); + newrfp |= inb(RPLH(base)) << 8; + newrfp %= RX_SIZE; + + #ifdef WISHIKNEWWHY + if(wlp_overrunning || newrfp == sp->rfp){ + printf("wl%d: odd RFPs:\n", unit); + printf(" i593_rfp %d stop %d newrfp %d sp->rfp %d\n", + i593_rfp, sp->stop, newrfp, sp->rfp); + } + #endif + + while(newrfp != sp->rfp) { + rp = newrfp; + /* find first frame */ + sanity = 0; + while ((f_start = wlp_start_of_frame(unit,rp)) != sp->rfp){ + if(f_start == -1 || sanity++ > 200){ + #if 0 + printf("wlp%d: cannot find start of frame\n", + unit); + printf(" i593_rfp %d stop %d newrfp %d sp->rfp %d\n", + i593_rfp, sp->stop, newrfp, sp->rfp); + #endif + return; + } + rp = f_start; + } + + stat_ptr = (rp - 7 + RX_SIZE) % RX_SIZE; + stat_ptr = read_ringbuf(unit, stat_ptr, &c, 1); + status = c; + stat_ptr = read_ringbuf(unit, stat_ptr, &c, 1); + status |= c << 8; + stat_ptr = read_ringbuf(unit, stat_ptr, &c, 1); + len = c; + stat_ptr = read_ringbuf(unit, stat_ptr, &c, 1); + len |= c << 8; + + if(!(status & RX_RCV_OK)) { + if(status & RX_NO_SFD) + ++wlp_cntrs[unit].rcv.frame; + if(status & RX_CRC_ERR) + ++wlp_cntrs[unit].rcv.crc; + if(status & RX_OVRRUN) + ++wlp_cntrs[unit].rcv.ovrnerrs; + #if 0 + printf("wl%d: packet not received ok, status = %x\n",unit,status); + #endif + WLPIF(unit).if_ierrors++; + } + else { + WLPIF(unit).if_ipackets++; + wlpread(unit, f_start, len - 2); + } + sp->rfp = rp; + } + + /* + * Update the frame stop register, but set it to less than + * the full 8K to allow space for 3 bytes of signal strength + * per packet. + */ + sp->stop = (i593_rfp + RX_SIZE - ((RX_SIZE / 64) * 3)) % RX_SIZE; + outb(LCCR(base), OP0_SWIT_TO_PORT_1 | CR0_CHNL); + outb(LCCR(base), CR1_STOP_REG_UPDATE | (sp->stop >> RX_SIZE_SHIFT)); + outb(LCCR(base), OP1_SWIT_TO_PORT_0); + } + + /* + * wlpread: + * + * This routine does the actual copy of data (including ethernet header + * structure) from the WaveLAN to an mbuf chain that will be passed up + * to the "if" (network interface) layer. NOTE: we currently + * don't handle trailer protocols, so if that is needed, it will + * (at least in part) be added here. The contents of the receive + * buffer are copied to an message chain that is then enqueued onto + * the appropriate "if" queue. + * + * input : board number, and an frame descriptor address + * output : the packet is put into an ipc_kmsg, and passed up + * assumes : if any errors occur, packet is "dropped on the floor" + * + */ + static void + wlpread(int unit, int fd_p, int len) + { + struct wlp_softc *is = WLPSOFTC(unit); + register struct ifnet *ifp = &WLPIF(unit); + struct mbuf *m, *tm; + int base = is->base; + u_char *mb_p; + u_short mlen; + u_short bytes_in_msg, bytes_in_mbuf, bytes; + struct ether_header eh; + + /* tbd. jrb. not initialized */ + bytes_in_msg = len - sizeof(struct ether_header); + #ifdef DEBUG + if (xtradebug) + printf("wl%d: entered wlpread() fd_p 0x%x len %d\n", + unit, fd_p, len); + #endif + if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { + printf("wl%d read(): board is not running.\n", ifp->if_unit); + /* XXX turn off interrupts? */ + } + wlp_cntrs[unit].rcv.rcv++; + + /* + * read out ether header. note: separate read from rest + * of data + */ + fd_p = read_ringbuf(unit, fd_p, (char *) &eh, sizeof(eh)); + #ifdef DEBUG + if (xtradebug) { + eh.ether_type = ntohs(eh.ether_type); + printf("wlpread: got packet, ether type %x\n", eh.ether_type); + eh.ether_type = htons(eh.ether_type); + } + #endif + #ifdef DUMPSIGNAL + printf("mac %s: signal %x silence %x quality %x\n", + ether_sprintf(eh.ether_shost), + wlpmmiread(base, MMC_SIGNAL_LVL) & 0x3f, + wlpmmiread(base, MMC_SILENCE_LVL) & 0x3f, + wlpmmiread(base, MMC_SIGN_QUAL) & 0x0f); + #endif + + MGETHDR(m, M_DONTWAIT, MT_DATA); + tm = m; + if (m == (struct mbuf *)0) { + /* + * not only do we want to return, we need to drop the packet on + * the floor to clear the interrupt. + */ + /* + return 1; + */ + return; + } + m->m_next = (struct mbuf *) 0; + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = len - sizeof(struct ether_header); + m->m_len = MHLEN; + if (bytes_in_msg >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + m->m_len = MCLBYTES; + #ifdef undef + else { + m_freem(m); + return; + } + #endif + } + mlen = 0; + bytes_in_mbuf = m->m_len; + /* + bytes_in_msg = len - sizeof(struct ether_header); + */ + mb_p = mtod(tm, u_char *); + do { + bytes = min(bytes_in_mbuf, bytes_in_msg); + fd_p = read_ringbuf(unit, fd_p, mb_p, bytes); + + mlen += bytes; + + if (!(bytes_in_msg -= bytes)) { + tm->m_len = mlen; + break; + } + + MGET(tm->m_next, M_DONTWAIT, MT_DATA); + tm = tm->m_next; + if (tm == (struct mbuf *)0) { + m_freem(m); + printf("wl%d read(): No mbuf nth\n", unit); + /* + return 0; + */ + return; + } + mlen = 0; + tm->m_len = MLEN; + bytes_in_mbuf = MLEN; + mb_p = mtod(tm, u_char *); + } while(1); + + #ifdef IF_CNTRS + wlp_ifcntrs.pkt_ein[log_2(len)]++; + if (len < 128) wlp_ifcntrs.pkt_lin[len>>3]++; + + if (ehp->ether_type == ETHERTYPE_ARP) { + wlp_ifcntrs.pkt_arp++; + if (pkt_narp) { + wlp_ifcntrs.pkt_ein[log_2(len)]--; + if (len < 128) wlp_ifcntrs.pkt_lin[len>>3]--; + } + } + #endif IF_CNTRS + if(gathersnr) { + u_char siglvl, sillvl, sigqual; + /* skip status and len fields */ + fd_p = read_ringbuf(unit, fd_p, NULL, 4); + /* read signal level, silence level and signal quality bytes */ + fd_p = read_ringbuf(unit, fd_p, &siglvl, 1); + fd_p = read_ringbuf(unit, fd_p, &sillvl, 1); + fd_p = read_ringbuf(unit, fd_p, &sigqual, 1); + wlpgetsnr(unit,&eh,siglvl,sillvl,sigqual); + } + #if NBPFILTER > 0 + if (WLPIF(unit).if_bpf) { + struct mbuf m0; + m0.m_len = sizeof eh; + m0.m_data = (caddr_t) &eh; + m0.m_next = m; + bpf_mtap(&WLPIF(unit), &m0); + + /* + * Note that the interface cannot be in promiscuous mode if + * there are no BPF listeners. And if we are in promiscuous + * mode, we have to check if this packet is really ours. + * + * logic: if promiscuous mode AND not multicast/bcast AND + * not to us, throw away + */ + if ((WLPIF(unit).if_flags & IFF_PROMISC) && + (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ + bcmp(eh.ether_dhost, WLPADDR(unit), + sizeof(eh.ether_dhost)) != 0 ) { + m_freem(m); + return; + } + } + #endif + + wl_cache_store(unit, base, &eh, m); + + /* + * Hand the packet to the Network Module + */ + ether_input(&WLPIF(unit), &eh, m); + /* + return 1; + */ + return; + } + + /* Read len bytes from ring buffer, starting at address addr. + * Result is stored in buf. Return value is addr to be used for next call. + */ + static int + read_ringbuf(int unit, int addr, char *buf, int len) + { + struct wlp_softc *is = WLPSOFTC(unit); + int base = is->base; + int i; + static int ring_ptr=0; + int chunk_len; + char *buf_ptr; + /* if buf is NULL, just increment the ring buffer pointer */ + if(buf == NULL) + return (ring_ptr - RX_BASE + len) % RX_SIZE + RX_BASE; + buf_ptr = buf; + ring_ptr = addr; + while(len > 0) { + /* position Program I/O Register at ring buffer pointer */ + outb(PIORL(base), ring_ptr & 0xff); + outb(PIORH(base), ((ring_ptr >> 8) & PIORH_MASK)); + /* determine how much we can read without wrapping around */ + if(addr + len < RX_BASE + RX_SIZE) + chunk_len = len; + else + chunk_len = RX_BASE + RX_SIZE - addr; + linb(PIOP(base), buf_ptr, chunk_len); + buf_ptr += chunk_len; + len -= chunk_len; + ring_ptr = (ring_ptr - RX_BASE + chunk_len) % RX_SIZE + RX_BASE; + } + return ring_ptr; + } + + /* + * wlpwatch(): + * + * This routine is the watchdog timer routine for the WaveLAN chip. If + * chip wedges, this routine will fire and cause a board reset and + * begin again. + * + * input : which board is timing out + * output : potential board reset if wedged + * + */ + + void + wlpwatch(struct ifnet *ifp) + { + int opri; + int unit = ifp->if_unit; + + if ((ifp->if_flags & IFF_UP) == 0) { + return; + } + + ifp->if_timer = 20; + wlp_cntrs[unit].watch++; + opri = splimp(); + wlphwrst(unit); + splx(opri); + } + + /* Gracefully turn off reception, and wait for any commands to complete */ + static void + wlp_graceful_shutdown(int unit) + { + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + int opri, status; + + wlpcmd(unit, "wlp_graceful_shutdown(): stop-rcv", + OP0_STOP_RCV, SR0_NO_RESULT); + /* spin until the receive unit is idle */ + do { + opri = splimp(); + outb(LCCR(base), OP0_NOP | CR0_STATUS_3); + status = inb(LCSR(base)); + splx(opri); + } while((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE); + + sp->cmd_request = TRUE; /* signal that we want to issue a command */ + /* spin until the chip finished executing any current command */ + do { + opri = splimp(); + outb(LCCR(base), OP0_NOP | CR0_STATUS_3); + status = inb(LCSR(base)); + splx(opri); + } while ((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE); + sp->cmd_request = FALSE; + } + + /* + * wlprustrt: + * + * This routine starts the receive unit running. First checks if the + * board is actually ready, then the board is instructed to receive + * packets again. + * + */ + void + wlprustrt(unit) + int unit; + { + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + + #ifdef DEBUG + if (xtradebug) + printf("wl%d: entered wlprustrt()\n",unit); + #endif + /* XXX check if board is running here? */ + + /* First disable reception in case it was already enabled */ + wlp_graceful_shutdown(unit); + + /* We now know that no command is being executed. */ + + /* set the receive frame pointer and stop pointer */ + sp->rfp = 0; + outb(LCCR(base), OP0_SWIT_TO_PORT_1 | CR0_CHNL); + /* Reset ring management. This sets the receive frame pointer to 1 */ + outb(LCCR(base), OP1_RESET_RING_MNGMT); + #if 0 + /* XXX the manual page 6-4 seems to indicate that the stop register + should be set as below */ + /* outb(LCCR(base), CR1_STOP_REG_UPDATE | + ((RX_SIZE - 0x40) >> RX_SIZE_SHIFT)); */ + #elif 0 + /* but I set it 0 instead */ + sp->stop = 0; + #else + /* but I set it to 3 bytes per packet less than 8K */ + sp->stop = (0 + RX_SIZE - ((RX_SIZE / 64) * 3)) % RX_SIZE; + #endif + outb(LCCR(base), CR1_STOP_REG_UPDATE | (sp->stop >> RX_SIZE_SHIFT)); + outb(LCCR(base), OP1_INT_ENABLE); + outb(LCCR(base), OP1_SWIT_TO_PORT_0); + + /* reset receive DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_RX_DMA_RESET); + DELAY(1000); + outb(HACR(base), HACR_PWR_STAT); + DELAY(1000); + + /* receive DMA on channel 1 */ + wlpcmd(unit, "wlprustrt(): rcv-enable", + CR0_CHNL | OP0_RCV_ENABLE, SR0_NO_RESULT); + return; + } + + /* + * wlpdiag: + * + * This routine does a 593 op-code number 7, and obtains the + * diagnose status for the WaveLAN. + * + */ + int + wlpdiag(unit) + int unit; + { + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + + #ifdef DEBUG + printf("wl%d: entered wlpdiag()\n",unit); + #endif + if(wlpcmd(unit, "wlpdiag(): diagnose", + OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED)) + return TRUE; + printf("wl%d: i82593 Self Test failed!\n", unit); + return FALSE; + } + + /* + * wlpconfig: + * + * This routine does a standard config of the WaveLAN board. + * + */ + #ifdef OLD + int + wlpconfig(int unit) + { + struct wlp_softc *is = WLPSOFTC(unit); + int base = is->base; + register struct ifnet *ifp = &WLPIF(unit); + #if MULTICAST + int cnt = 0; + struct ether_multi *enm; + struct ether_multistep step; + #endif MULTICAST + + #ifdef DEBUG + printf("wl%d: wlpconfig(), size %d\n", + unit, sizeof(struct i82593_conf_block)); + #endif + + bzero(&is->cfblk, sizeof(struct i82593_conf_block)); + is->cfblk.d6mod = FALSE; /* Run in 82593 advanced mode */ + if (ifp->if_flags & IFF_LINK0) + is->cfblk.loopback = 1; /* internal loopback */ + is->cfblk.fifo_limit = 6; /* = 48 bytes rx and tx fifo thresholds */ + is->cfblk.forgnesi = FALSE; /* 0=82C501, 1=AMD7992B compatibility */ + is->cfblk.fifo_32 = 0; + is->cfblk.throttle_enb = TRUE; + is->cfblk.contin = TRUE; /* enable continous mode */ + is->cfblk.addr_len = WAVELAN_ADDR_SIZE; + is->cfblk.preamb_len = 2; /* 7 byte preamble */ + is->cfblk.lin_prio = 0; /* conform to 802.3 backoff algoritm */ + is->cfblk.exp_prio = 0; /* conform to 802.3 backoff algoritm */ + is->cfblk.bof_met = 0; /* conform to 802.3 backoff algoritm */ + is->cfblk.ifrm_spc = 6; /* 96 bit times interframe spacing */ + is->cfblk.slottim_low = 0x10 & 0x7; /* 512 bit times slot time */ + is->cfblk.slottim_hi = 0x10 >> 3; + is->cfblk.max_retr = 15; + if(WLPIF(unit).if_flags & (IFF_PROMISC|IFF_LINK1)) + is->cfblk.prmisc = TRUE; + else + is->cfblk.prmisc = FALSE; + is->cfblk.crs_1 = TRUE; /* Transmit without carrier sense */ + is->cfblk.nocrc_ins = FALSE; /* 82593 generates CRC */ + is->cfblk.crc_1632 = FALSE; /* 32-bit Autodin-II CRC */ + is->cfblk.crs_cdt = FALSE; /* CD not to be interpreted as CS */ + is->cfblk.cs_filter = 0; /* CS is recognized immediately */ + is->cfblk.crs_src = FALSE; /* External carrier sense */ + is->cfblk.cd_filter = 0; /* CD is recognized immediately */ + is->cfblk.min_fr_len = /* Minimum frame length 64 bytes */ + (sizeof(struct ether_header) + ETHERMIN + sizeof(long)) >> 2; + is->cfblk.lng_typ = FALSE; /* Length field > 1500 = type field */ + is->cfblk.lng_fld = TRUE; /* Disable 802.3 length field check */ + is->cfblk.rxcrc_xf = TRUE; /* Don't transfer CRC to memory */ + is->cfblk.artx = TRUE; /* Disable automatic retransmission */ + is->cfblk.sarec = TRUE; /* Disable source addr trig of CD */ + is->cfblk.tx_jabber = TRUE; /* Disable jabber jam sequence */ + is->cfblk.hash_1 = FALSE; /* Use bits 0-5 in mc address hash */ + is->cfblk.lbpkpol = TRUE; /* Loopback pin active high */ + is->cfblk.fdx = FALSE; /* Disable full duplex operation */ + is->cfblk.dummy_6 = 0x3f; /* all ones */ + is->cfblk.mult_ia = FALSE; /* No multiple individual addresses */ + is->cfblk.dis_bof = FALSE; /* Disable the backoff algorithm ?! */ + is->cfblk.dummy_1 = TRUE; /* set to 1 */ + is->cfblk.tx_ifs_retrig = 3; /* Hmm... Disabled */ + #if MULTICAST + #if 0 + if(WLPIF(unit).if_flags & IFF_ALLMULTI) + is->cfblk.mc_all = TRUE; + else + is->cfblk.mc_all = FALSE; + #else + /* TBD */ + is->cfblk.mc_all = TRUE; + #endif + #endif MULTICAST + is->cfblk.rcv_mon = 0; /* Monitor mode disabled */ + is->cfblk.frag_acpt = FALSE; /* Do not accept fragments */ + is->cfblk.tstrttrs = FALSE; /* No start transmission threshold */ + is->cfblk.fretx = TRUE; /* FIFO automatic retransmission */ + is->cfblk.syncrqs = TRUE; /* Synchronous DRQ deassertion... */ + is->cfblk.sttlen = TRUE; /* 6 byte status registers */ + is->cfblk.rx_eop = TRUE; /* Signal EOP on packet reception */ + is->cfblk.tx_eop = TRUE; /* Signal EOP on packet transmission */ + is->cfblk.rbuf_size = RX_SIZE>>11; /* Set receive buffer size */ + is->cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */ + + outb(PIORL(base), TX_BASE & 0xff); + outb(PIORH(base), ((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX); + outb(PIOP(base),sizeof(struct i82593_conf_block) & 0xff); /* lsb */ + outb(PIOP(base),sizeof(struct i82593_conf_block) >> 8); /* msb */ + loutb(PIOP(base), &is->cfblk, sizeof(struct i82593_conf_block)); + /* reset transmit DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_TX_DMA_RESET); + DELAY(1000); + outb(HACR(base), HACR_PWR_STAT); + DELAY(1000); + if(!wlpcmd(unit, "wlpconfig(): configure", + OP0_CONFIGURE, SR0_CONFIGURE_DONE)) + return FALSE; + + #if 0 + #ifdef ORIGINAL_CONFIG + /* + * below is the default board configuration from p2-28 from 586 book + */ + configure.fifolim_bytecnt = 0x080c; + configure.addrlen_mode = 0x2600; + configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */ + configure.slot_time = 0xf00c; /* slottime=12 */ + configure.hardware = 0x0008; /* tx even w/o CD */ + configure.min_frame_len = 0x0040; + #else + /* This is the configuration block suggested by Marc Meertens + * in an e-mail message to John + * Ioannidis on 10 Nov 92. + */ + configure.fifolim_bytecnt = 0x040c; + configure.addrlen_mode = 0x0600; + configure.linprio_interframe = 0x2060; + configure.slot_time = 0xf000; + configure.hardware = 0x0008; /* tx even w/o CD */ + configure.min_frame_len = 0x0040; + #endif ORIGINAL_CONFIG + #endif 0 + + #if MULTICAST + outb(PIORL(base), (TX_BASE + 2) & 0xff); + outb(PIORH(base), (((TX_BASE + 2) >> 8) & PIORH_MASK) | PIORH_SEL_TX); + ETHER_FIRST_MULTI(step, &wlp_ac[unit], enm); + while (enm != NULL) { + unsigned int lo, hi; + lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8) + + enm->enm_addrlo[5]; + hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8) + + enm->enm_addrhi[5]; + while(lo <= hi) { + outb(PIOP(base),enm->enm_addrlo[0]); + outb(PIOP(base),enm->enm_addrlo[1]); + outb(PIOP(base),enm->enm_addrlo[2]); + outb(PIOP(base),lo >> 16); + outb(PIOP(base),(lo >> 8) & 0xff); + outb(PIOP(base),lo & 0xff); + ++cnt; + ++lo; + } + ETHER_NEXT_MULTI(step, enm); + } + /* write the size of the multicast address area */ + outb(PIORL(base), TX_BASE & 0xff); + outb(PIORH(base), ((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX); + outb(PIOP(base), (cnt * WAVELAN_ADDR_SIZE) & 0xff); + outb(PIOP(base), (cnt * WAVELAN_ADDR_SIZE) >> 8); + /* reset transmit DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_TX_DMA_RESET); + if(!wlpcmd(unit, "wlpconfig(): mc-setup", + OP0_MC_SETUP, SR0_MC_SETUP_DONE)) { + return FALSE; + } + #endif MULTICAST + + outb(PIORL(base), TX_BASE & 0xff); + outb(PIORH(base), ((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX); + outb(PIOP(base), WAVELAN_ADDR_SIZE); /* byte count lsb */ + outb(PIOP(base), 0); /* byte count msb */ + loutb(PIOP(base), WLPADDR(unit), WAVELAN_ADDR_SIZE); + /* reset transmit DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_TX_DMA_RESET); + DELAY(1000); + outb(HACR(base), HACR_PWR_STAT); + DELAY(1000); + if(!wlpcmd(unit, "wlpconfig(): ia-setup", + OP0_IA_SETUP, SR0_IA_SETUP_DONE)) { + return FALSE; + } + return TRUE; + } + #else + #define matt + int + wlpconfig(int unit) + { + struct wlp_softc *sc = WLPSOFTC(unit); + int base = sc->base; + register struct ifnet *ifp = &WLPIF(unit); + #ifdef MULTICAST + int cnt = 0; + struct ether_multi *enm; + struct ether_multistep step; + #endif + + #ifdef DEBUG + printf("wl%d: wlpconfig(), size %d\n", + unit, sizeof(struct i82593_conf_block)); + #endif + + bzero(&sc->cfblk, sizeof(struct i82593_conf_block)); + /* byte 0 -- 0x25 (0x86??) XXX */ + sc->cfblk.forgnesi = FALSE; /* 0=82C501, 1=AMD7992B compatibility */ + sc->cfblk.d6mod = FALSE; /* Run in 82593 advanced mode */ + #ifdef matt + sc->cfblk.fifo_limit = 5; /* = 32 byte rx and tx fifo thresholds */ + sc->cfblk.fifo_32 = 1; + sc->cfblk.throttle_enb = FALSE; + #else + sc->cfblk.fifo_limit = 6; /* = 48 byte rx and tx fifo thresholds */ + sc->cfblk.fifo_32 = 0; + sc->cfblk.throttle_enb = TRUE; + #endif + + /* byte 1 -- 0x80 (OK) */ + sc->cfblk.contin = TRUE; /* enable continous mode */ + + /* byte 2 -- 0x0E (0x26??) XXX */ + sc->cfblk.addr_len = WAVELAN_ADDR_SIZE; + #ifdef matt + sc->cfblk.acloc = FALSE; + #if 0 + sc->cfblk.acloc = TRUE; + #endif + sc->cfblk.preamb_len = 0; /* 1 (2^(n+1) - 1) byte preamble */ + #else + sc->cfblk.acloc = FALSE; + sc->cfblk.preamb_len = 2; /* 7 (2^(n+1) - 1) byte preamble */ + #endif + if (ifp->if_flags & IFF_LOOPBACK) + sc->cfblk.loopback = 1; /* internal loopback */ + + /* byte 3 -- 0xD0 (0x00??) XXX */ + sc->cfblk.lin_prio = 0; /* conform to 802.3 backoff algoritm */ + #ifdef matt + sc->cfblk.exp_prio = 5; /* conform to 802.3 backoff algoritm */ + sc->cfblk.bof_met = 1; /* conform to 802.3 backoff algoritm */ + #else + sc->cfblk.exp_prio = 0; /* conform to 802.3 backoff algoritm */ + sc->cfblk.bof_met = 0; /* conform to 802.3 backoff algoritm */ + #endif + + /* byte 4 -- 0x20 (0x60??) XXX */ + #ifdef matt + sc->cfblk.ifrm_spc = 2; /* 32 bit times interframe spacing */ + #else + sc->cfblk.ifrm_spc = 6; /* 96 bit times interframe spacing */ + #endif + + /* byte 5 -- 0x20 (0x00??) XXX */ + /* byte 6 -- 0xF0 (0xF2??) XXX */ + #ifdef matt + sc->cfblk.slottim_low = (0x20 >> 5); /* 64 bit times slot time */ + sc->cfblk.slottim_hi = (0x20 >> 8); + #else + sc->cfblk.slottim_low = (0x200 >> 5); /* 512 bit times slot time */ + sc->cfblk.slottim_hi = (0x200 >> 8); + #endif + sc->cfblk.max_retr = 15; + + /* byte 7 -- 0x08 (OK) */ + sc->cfblk.prmisc = (WLPIF(unit).if_flags & IFF_PROMISC) != 0; + sc->cfblk.crs_1 = TRUE; /* Transmit without carrier sense */ + sc->cfblk.nocrc_ins = FALSE; /* 82593 generates CRC */ + sc->cfblk.crc_1632 = FALSE; /* 32-bit Autodin-II CRC */ + sc->cfblk.crs_cdt = FALSE; /* CD not to be interpreted as CS */ + + /* byte 8 -- 0x00 (OK) */ + sc->cfblk.cs_filter = 0; /* CS is recognized immediately */ + sc->cfblk.crs_src = FALSE; /* External carrier sense */ + sc->cfblk.cd_filter = 0; /* CD is recognized immediately */ + + /* byte 9 -- 0x3C (0x10??) XXX */ + sc->cfblk.min_fr_len = /* Minimum frame length 64 bytes */ + (sizeof(struct ether_header) + ETHERMIN + sizeof(long)) >> 2; + + /* byte 10 -- 0xFF (0xBE??) XXX */ + sc->cfblk.lng_typ = FALSE; /* Length field > 1500 = type field */ + sc->cfblk.lng_fld = TRUE; /* Disable 802.3 length field check */ + sc->cfblk.rxcrc_xf = TRUE; /* Don't transfer CRC to memory */ + sc->cfblk.artx = TRUE; /* Disable automatic retransmission */ + sc->cfblk.sarec = TRUE; /* Disable source addr trig of CD */ + sc->cfblk.tx_jabber = TRUE; /* Disable jabber jam sequence */ + sc->cfblk.hash_1 = FALSE; /* Use bits 0-5 in mc address hash */ + sc->cfblk.lbpkpol = TRUE; /* Loopback pin active high */ + + /* byte 11 -- 0x00 (OK) */ + sc->cfblk.fdx = FALSE; /* Disable full duplex operation */ + + /* byte 12 -- 0x3f (OK) */ + sc->cfblk.dummy_6 = 0x3f; /* all ones */ + sc->cfblk.mult_ia = FALSE; /* No multiple individual addresses */ + sc->cfblk.dis_bof = FALSE; /* Disable the backoff algorithm ?! */ + + /* byte 13 -- 0x07 (OK) */ + sc->cfblk.dummy_1 = TRUE; /* set to 1 */ + sc->cfblk.tx_ifs_retrig = 3; /* Hmm... Disabled */ + #ifdef MULTICAST + #if 0 + sc->cfblk.mc_all = (WLPIF(unit).if_flags & IFF_ALLMULTI) != 0; + #endif + sc->cfblk.mc_all = TRUE; + #endif /* MULTICAST */ + sc->cfblk.rcv_mon = 0; /* Monitor mode disabled */ + sc->cfblk.frag_acpt = FALSE; /* Do not accept fragments */ + sc->cfblk.tstrttrs = FALSE; /* No start transmission threshold */ + + /* byte 14 -- 0xE1 (OK) */ + sc->cfblk.fretx = TRUE; /* FIFO automatic retransmission */ + sc->cfblk.syncrqs = TRUE; /* Synchronous DRQ deassertion... */ + sc->cfblk.sttlen = TRUE; /* 6 byte status registers */ + sc->cfblk.rx_eop = TRUE; /* Signal EOP on packet reception */ + sc->cfblk.tx_eop = TRUE; /* Signal EOP on packet transmission */ + + /* byte 15 -- 0x24 (OK) */ + sc->cfblk.rbuf_size = RX_SIZE >> 11; /* Set receive buffer size */ + sc->cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */ + + outb(PIORL(base), TX_BASE & 0xff); + outb(PIORH(base), ((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX); + outb(PIOP(base),sizeof(struct i82593_conf_block) & 0xff); /* lsb */ + outb(PIOP(base),sizeof(struct i82593_conf_block) >> 8); /* msb */ + loutb(PIOP(base), &sc->cfblk, sizeof(struct i82593_conf_block)); + /* reset transmit DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_TX_DMA_RESET); + DELAY(1000); + outb(HACR(base), HACR_PWR_STAT); + DELAY(1000); + if(!wlpcmd(unit, "wlpconfig(): configure", + OP0_CONFIGURE, SR0_CONFIGURE_DONE)) + return FALSE; + + #if 0 + #ifdef ORIGINAL_CONFIG + /* + * below is the default board configuration from p2-28 from 586 book + */ + configure.fifolim_bytecnt = 0x080c; + configure.addrlen_mode = 0x2600; + configure.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */ + configure.slot_time = 0xf00c; /* slottime=12 */ + configure.hardware = 0x0008; /* tx even w/o CD */ + configure.min_frame_len = 0x0040; + #else + /* This is the configuration block suggested by Marc Meertens + * in an e-mail message to John + * Ioannidis on 10 Nov 92. + */ + configure.fifolim_bytecnt = 0x040c; + configure.addrlen_mode = 0x0600; + configure.linprio_interframe = 0x2060; + configure.slot_time = 0xf000; + configure.hardware = 0x0008; /* tx even w/o CD */ + configure.min_frame_len = 0x0040; + #endif ORIGINAL_CONFIG + #endif 0 + + #ifdef MULTICAST + outb(PIORL(base), (TX_BASE + 2) & 0xff); + outb(PIORH(base), (((TX_BASE + 2) >> 8) & PIORH_MASK) | PIORH_SEL_TX); + ETHER_FIRST_MULTI(step, &wlp_ac[unit], enm); + while (enm != NULL) { + unsigned int lo, hi; + lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8) + + enm->enm_addrlo[5]; + hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8) + + enm->enm_addrhi[5]; + while(lo <= hi) { + outb(PIOP(base),enm->enm_addrlo[0]); + outb(PIOP(base),enm->enm_addrlo[1]); + outb(PIOP(base),enm->enm_addrlo[2]); + outb(PIOP(base),lo >> 16); + outb(PIOP(base),(lo >> 8) & 0xff); + outb(PIOP(base),lo & 0xff); + ++cnt; + ++lo; + } + ETHER_NEXT_MULTI(step, enm); + } + /* write the size of the multicast address area */ + outb(PIORL(base), TX_BASE & 0xff); + outb(PIORH(base), ((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX); + outb(PIOP(base), (cnt * WAVELAN_ADDR_SIZE) & 0xff); + outb(PIOP(base), (cnt * WAVELAN_ADDR_SIZE) >> 8); + /* reset transmit DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_TX_DMA_RESET); + if(!wlpcmd(unit, "wlpconfig(): mc-setup", + OP0_MC_SETUP, SR0_MC_SETUP_DONE)) { + return FALSE; + } + #endif MULTICAST + + #if 0 + /* + * zero out the receive buffer space. + */ + outb(PIORL(base), RX_BASE & 0xff); + outb(PIORH(base), ((RX_BASE >> 8) & PIORH_MASK)); + for (i = 0; i < RX_SIZE; i++) + outb(PIOP(base), 0); + + outb(PIORL(base), RX_BASE & 0xff); + outb(PIORH(base), ((RX_BASE >> 8) & PIORH_MASK)); + #endif + + outb(PIORL(base), TX_BASE & 0xff); + outb(PIORH(base), ((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX); + outb(PIOP(base), WAVELAN_ADDR_SIZE); /* byte count lsb */ + outb(PIOP(base), 0); /* byte count msb */ + loutb(PIOP(base), WLPADDR(unit), WAVELAN_ADDR_SIZE); + /* reset transmit DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_TX_DMA_RESET); + DELAY(1000); + outb(HACR(base), HACR_PWR_STAT); + DELAY(1000); + if(!wlpcmd(unit, "wlpconfig(): ia-setup", + OP0_IA_SETUP, SR0_IA_SETUP_DONE)) + return FALSE; + return TRUE; + } + #endif + + void + wlpdump(int unit) + { + struct wlp_softc *is = WLPSOFTC(unit); + int base = is->base; + int i, c; + + /* disable receiver so we can use channel 1 */ + outb(LCCR(base), OP0_RCV_DISABLE); + + outb(HACR(base), HACR_PWR_STAT | HACR_RX_DMA_RESET); + DELAY(1000); + outb(HACR(base), HACR_PWR_STAT); + DELAY(1000); + + /* dump into receive buffer */ + wlpcmd(unit, "wlpdump(): dump", CR0_CHNL|OP0_DUMP, SR0_DUMP_DONE); + + /* set read pointer to start of receive buffer */ + outb(PIORL(base), 0); + outb(PIORH(base), 0); + + printf("wlp%d dump:", unit); + for(i = 0; i < 72; i++){ + if((i % 16) == 0) + printf("\n"); + c = inb(PIOP(base)); + printf("%02x ", c); + } + printf("\n"); + + /* enable the receiver again */ + wlprustrt(unit); + } + + /* + * wlpxmt: + * + * This routine fills in the appropriate registers and memory + * locations on the WaveLAN board and starts the board off on + * the transmit. + * + * input : board number of interest, and a pointer to the mbuf + * output : board memory and registers are set for xfer and attention + * + */ + void + wlpxmt(int unit, struct mbuf *m) + { + struct wlp_softc *is = WLPSOFTC(unit); + register u_short xmtdata_p, xmtdata_base = TX_BASE; + u_short clen = 0; /* total pkt data len */ + int count; /* data in current mbuf */ + int base = is->base; + register struct ether_header *eh_p = mtod(m, struct ether_header *); + struct mbuf *tm_p = m; + u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header); + + #ifdef DEBUG + if (xtradebug) + printf("wlp%d: wlpxmt, type 0x%04x\n", unit, eh_p->ether_type); + #endif + + xmtdata_p = xmtdata_base + 2; /* skip length field */ + outb(PIORL(base), xmtdata_p & 0xff); + outb(PIORH(base), ((xmtdata_p >> 8) & PIORH_MASK) | PIORH_SEL_TX); + loutb(PIOP(base), eh_p->ether_dhost, WAVELAN_ADDR_SIZE); + outb(PIOP(base), eh_p->ether_type & 0xff); + outb(PIOP(base), eh_p->ether_type >> 8); + + count = m->m_len - sizeof(struct ether_header); + clen = 0; + while(1){ + if (count) { + loutb(PIOP(base), mb_p, count); + clen += count; + } + if ((tm_p = tm_p->m_next) == (struct mbuf *)0) + break; + count = tm_p->m_len; + mb_p = mtod(tm_p, u_char *); + } + + if (clen < ETHERMIN) { + for (; clen < ETHERMIN; ++clen) + outb(PIOP(base), 0); + } + outb(PIOP(base), OP0_NOP); /* Indicate end of transmit chain */ + /* write length of data buffer */ + clen += WAVELAN_ADDR_SIZE + sizeof(eh_p->ether_type); + outb(PIORL(base), xmtdata_base & 0xff); + outb(PIORH(base), ((xmtdata_base >> 8) & PIORH_MASK) | PIORH_SEL_TX); + outb(PIOP(base), clen & 0xff); /* lsb */ + outb(PIOP(base), clen >> 8); /* msb */ + #ifdef IF_CNTRS + clen += 4 /* crc */; + wlp_ifcntrs.pkt_eout[log_2(clen)]++; + if (clen < 128) wlp_ifcntrs.pkt_lout[clen>>3]++; + #endif IF_CNTRS + + /* reset transmit DMA pointer */ + outb(HACR(base), HACR_PWR_STAT | HACR_TX_DMA_RESET); + DELAY(1000); + outb(HACR(base), HACR_PWR_STAT); + DELAY(1000); + /* transmit command */ + wlpcmd(unit, "wlpxmt(): transmit", OP0_TRANSMIT, SR0_NO_RESULT); + m_freem(m); + return; + } + + /* + * wlpintr: + * + * This function is the interrupt handler for the WaveLAN + * board. This routine will be called whenever either a packet + * is received, or a packet has successfully been transfered and + * the unit is ready to transmit another packet. + * + * input : board number that interrupted + * output : either a packet is received, or a packet is transfered + * + */ + void + wlpintr(int unit) + { + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + int next, x, opri; + int i, expected = 0; + u_short int_type; + int status0; + + #ifdef DEBUG + if (xtradebug) + printf("wl%d: wlpintr() called\n",unit); + #endif + if(sp->gone) + return; + if (sp->seated == FALSE) { + printf("wl%d intr(): board not seated\n", unit); + return; + } + for(expected = 0; ; expected = 1) { + outb(LCCR(base), CR0_STATUS_0 | OP0_NOP); + status0 = inb(LCSR(base)); + /* return if no interrupt from 82593 */ + if(!(status0 & SR0_INTERRUPT)) { + return; + } + sp->status = status0; + if (status0 & SR0_RECEPTION) { + if((status0 & SR0_EVENT_MASK) == SR0_STOP_REG_HIT) { + #if 0 + printf("wl%d: receive buffer overflow\n", unit); + #endif + wlp_cntrs[unit].rcv.ovw++; + WLPIF(unit).if_ierrors++; + #if 0 + wlp_overrunning = 1; + #endif + outb(LCCR(base), CR0_INT_ACK | OP0_NOP); + wlphwrst(unit); + return; + + } + wlprcv(unit); + wlp_overrunning = 0; + if (status0 & SR0_EXECUTION) { + printf("wl%d: interrupt is both rx and tx, status0 = %x\n", + unit,status0); + } + /* acknowledge the interrupt */ + outb(LCCR(base), CR0_INT_ACK | OP0_NOP); + continue; + } + else + if (!(status0 & SR0_EXECUTION)) { + printf("wl%d: interrupt is neither rx or tx, status0 = %x\n", + unit,status0); + /* acknowledge the interrupt */ + outb(LCCR(base), CR0_INT_ACK | OP0_NOP); + break; + } + if(sp->cmd_wait) { + /* We are waiting for a command to complete */ + sp->cmd_wait = FALSE; /* signal command completed */ + /* acknowledge the interrupt */ + outb(LCCR(base), CR0_INT_ACK | OP0_NOP); + /* If we had to defer call to wlpstart previously, + make up for it by calling wlpstart now */ + if(sp->deferred) { + wlpstart(&(WLPIF(unit))); + sp->deferred = FALSE; + } + continue; + } + if((status0 & SR0_EVENT_MASK) == SR0_TRANSMIT_DONE || + (status0 & SR0_EVENT_MASK) == SR0_RETRANSMIT_DONE) { + int tx_status; + tx_status = inb(LCSR(base)); + tx_status |= inb(LCSR(base)) << 8; + if (!(tx_status & TX_OK)) { + if (tx_status & TX_FRTL) { + if (xmt_watch) + printf("wl%d: frame too long\n", unit); + WLPIF(unit).if_oerrors++; + } + if (tx_status & TX_UND_RUN) { + if (xmt_watch) + printf("wl%d: DMA underrun\n", unit); + wlp_cntrs[unit].xmt.dma++; + WLPIF(unit).if_oerrors++; + } + if (tx_status & TX_LOST_CTS) { + if (xmt_watch) + printf("wl%d: no CTS\n", unit); + wlp_cntrs[unit].xmt.nocts++; + WLPIF(unit).if_oerrors++; + } + if (tx_status & TX_LOST_CRS) { + /* if (xmt_watch) + printf("wl%d: no carrier\n", unit); */ + wlp_cntrs[unit].xmt.nodcd++; + } + /* Ignore late collisions. Act only when maximum + retransmit attempts exceeded */ + if (tx_status & TX_COLL) { + if (tx_status & TX_MAX_COL) { + if (xmt_watch) + printf("wl%d: channel congestion\n", unit); + if (!(tx_status & TX_NCOL_MASK)) { + WLPIF(unit).if_collisions += 0x10; + wlp_cntrs[unit].xmt.ncoll += 0x10; + } + } + wlp_cntrs[unit].xmt.coll++; + WLPIF(unit).if_oerrors++; + } + } + if(tx_status & TX_DEFER) { + if (xmt_watch) + printf("wl%d: channel jammed\n",unit); + wlp_cntrs[unit].xmt.defer++; + } + if (tx_status & TX_HRT_BEAT) { + if (xmt_watch) + printf("wl%d: heart beat\n", unit); + wlp_cntrs[unit].xmt.heart++; + } + WLPIF(unit).if_collisions += (tx_status & TX_NCOL_MASK); + wlp_cntrs[unit].xmt.ncoll += (tx_status & TX_NCOL_MASK); + wlp_cntrs[unit].xmt.xmti++; + sp->tbusy = FALSE; + WLPIF(unit).if_flags &= ~IFF_OACTIVE; + /* acknowledge the interrupt */ + outb(LCCR(base), CR0_INT_ACK | OP0_NOP); + /* Defer call to wlpstart if we are waiting to be + able to issue a command */ + if(sp->cmd_request) { + sp->deferred = TRUE; + break; + } + wlpstart(&(WLPIF(unit))); + } + else { + printf("wlp%d: unknown interrupt, status0 = %02x\n", + unit, status0); + /* acknowledge the interrupt */ + outb(LCCR(base), CR0_INT_ACK | OP0_NOP); + } + } + return; + } + + /* Send a command to the 82593 chip. Must be called with interrupts enabled */ + + int + wlpcmd(int unit, char *str, int cmd, int result) + { + struct wlp_softc *sp = WLPSOFTC(unit); + int base = sp->base; + int status, spin; + int opri; + + sp->cmd_request = TRUE; /* signal that we want to issue a command */ + /* spin until the chip finished executing any current command */ + do { + opri = splimp(); + outb(LCCR(base), OP0_NOP | CR0_STATUS_3); + status = inb(LCSR(base)); + splx(opri); + } while ((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE); + + sp->cmd_wait = TRUE; /* signal that we are waiting for command completion */ + sp->cmd_request = FALSE; + outb(LCCR(base), cmd); + if(result == SR0_NO_RESULT) { /* Return immediately */ + sp->cmd_wait = FALSE; + /* if a call to wlpstart was deferred, make up for it now */ + if(sp->deferred) { + wlpstart(&(WLPIF(unit))); /* idempotent */ + sp->deferred = FALSE; + } + return TRUE; + } + + /* interrupts better be enabled while we busy wait */ + /* but in_ifinit() turns them off! */ + /* could enable just the WaveLAN's IRQ... */ + for(spin = 0; spin < 10000000 && sp->cmd_wait; spin++) + ; + + if(sp->cmd_wait){ + outb(LCCR(base), OP0_NOP); + status = inb(LCSR(base)); + if(status & 0x80){ + wlpintr(unit); + } else { + sp->cmd_wait = 0; /* XXX */ + printf("wlpcmd timeout, status0 %02x\n", status); + return(FALSE); + } + } + + /* check the return code, provided by the interrupt handler */ + if((sp->status & SR0_EVENT_MASK) != result) { + printf("wl%d: %s failed, status0 = %x\n", unit, str, sp->status); + return FALSE; + } + return TRUE; + } + + /* Calculates the SNR ratio. Ignores sigqual and the ethernet header for + the time being */ + static void + wlpgetsnr(int unit, struct ether_header *ehp, + u_char siglvl, u_char sillvl, u_char sigqual) + { + int s; + int snrindex; + + if((s = (siglvl & 0x3f)) > 0) { + s -= (sillvl & 0x3f) - 0x2d; + if(s >= 0x38) + snrindex = 4; + else if(s >= 0x2a) + snrindex = 3; + else if(s >= 0x1c) + snrindex = 2; + else if(s >= 0x0e) + snrindex = 1; + else if(s >= 0) + snrindex = 0; + else { + printf("wl%d: bogus snr level\n",unit); + return; + } + wlp_cntrs[unit].rcv.snr[snrindex]++; + } + } + + + + /* + * wlpioctl: + * + * This routine processes an ioctl request from the "if" layer + * above. + * + * input : pointer the appropriate "if" struct, command, and data + * output : based on command appropriate action is taken on the + * WaveLAN board(s) or related structures + * return : error is returned containing exit conditions + * + */ + int + wlpioctl(ifp, cmd, data) + struct ifnet *ifp; + int cmd; + caddr_t data; + { + register struct ifaddr *ifa = (struct ifaddr *)data; + register struct ifreq *ifr = (struct ifreq *)data; + int unit = ifp->if_unit; + register struct wlp_softc *sc = WLPSOFTC(unit); + short mode = 0; + short base; + int opri, error = 0; + u_short tmp; + int reinit = 0; + + + #ifdef DEBUG + printf("wlp%d: entered wlpioctl(), cpl %x\n",unit, cpl); + #endif + + /* The card might have been ejected. */ + if(sc == 0) + return(EINVAL); + + base = sc->base; + switch (cmd) { + case SIOCSIFADDR: + #ifdef DEBUG + printf("SIOCSIFADDR\n"); + #endif + /* Set own IP address and enable interface */ + ifp->if_flags |= IFF_UP; + wlpinit(unit); + switch (ifa->ifa_addr->sa_family) { + #ifdef INET + case AF_INET: + opri = splimp(); + arp_ifinit((struct arpcom *)ifp, ifa); + splx(opri); + break; + #endif + #ifdef NS + case AF_NS: + { + register struct ns_addr *ina = + &(IA_SNS(ifa)->sns_addr); + if (ns_nullhost(*ina)) + ina->x_host = *(union ns_host *)(ds->wlp_addr); + else + wlpsetaddr(ina->x_host.c_host, unit); + break; + } + #endif + } + break; + case SIOCSIFFLAGS: + #ifdef DEBUG + printf("SIOCSIFFLAGS\n"); + #endif + wlpinit(unit); + reinit = 1; + /* TBD. need to reinit if promisc mode set ? */ + if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) { + printf("wlp%d ioctl(): board is not running\n", unit); + sc->flags &= ~DSF_RUNNING; + ifp->if_timer = 0; + /* TBD turn off interrupts? */ + } else if ((ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0)) { + if (reinit == 0) + wlpinit(unit); + } + + if(ifp->if_flags & IFF_LINK2) + wlpdump(unit); + break; + #ifdef MULTICAST + case SIOCADDMULTI: + case SIOCDELMULTI: + error = (cmd == SIOCADDMULTI) ? + ether_addmulti(ifr, &wlp_ac[unit]) : + ether_delmulti(ifr, &wlp_ac[unit]); + wlphwrst(unit); + if (error == ENETRESET) { + wlpinit(unit); + error = 0; + } + break; + #endif MULTICAST + case SIOCGIFADDR: + bcopy(WLPADDR(unit), ifr->ifr_addr.sa_data, WAVELAN_ADDR_SIZE); + break; + /* get the NWID out of the sc since we stored it there + */ + case SIOCGWLNWID: + ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]); + break; + + /* set the nwid + */ + case SIOCSWLNWID: + /* root only + * we need to check suser status but the p + * parameter is not passed down to us. + * This is not good. XXX. jrb + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) + break; + */ + wlpsetnwid(unit, base, (int)ifr->ifr_data); + break; + + default: + error = EINVAL; + } + return (error); + } + + + static + void + wlpsetnwid(int unit, int base, int data) + { + struct wlp_softc *sp = WLPSOFTC(unit); + + sp->nwid[0] = data >> 8; + sp->nwid[1] = data & 0xff; + + MMI_WRITE(MMC_NETW_ID_L,sp->nwid[1]); + MMI_WRITE(MMC_NETW_ID_H,sp->nwid[0]); + } + + /* following 2 routines are addition to do wlansignal caching + * (1) int OldestEntryNdx( void) + * utility fn: used by REVERSEage(lowest age is oldest pkt.) LRU alg. + * to find oldest entry in cache + * (2) void wl_cache_store (int unit, int base, struct ether_header *eh, + * struct mbuf *m) + * routine to store the wlansignal strength, to be used + * in the handoff algorithm in Mobile-IP or other uses. + */ + + static + int OldestEntryNdx( void ) + { + int i; + int OldestEntryAge; + int OldestEntryIndex; + + OldestEntryAge = MAX_AGE; + OldestEntryIndex = 0; + + for(i = 0; i < NextCacheItem; i++) { + if ( w_sigcache[i].age < OldestEntryAge ) { + OldestEntryAge = w_sigcache[i].age; + OldestEntryIndex = i; + } + } + return (OldestEntryIndex); + } + + + /* + * for this input packet, + * if packet is not IP packet + * return; + * lookup the MAC address in array + * if it's not there or there is no room + * find a free slot + * simple LRU, free pointer and wrap it if full + * at this point we have a pointer to an entry + * read out and store signal/silence/quality from rmodem + * extract ip src from ip header and store + * when AGE overflows (this may take awhile) + * resort array + * + * Some things to think about: + * note that no space is malloced. + * We might hash the mac address if the cache were bigger. + * It is not clear that the cache is big enough. + * It is also not clear how big it should be. + * The cache is IP-specific. We don't care about that as + * we want it to be IP-specific. + * The last N recv. packets are saved. This will tend + * to reward agents and mobile hosts that beacon. + * That is probably fine for mobile ip. + * Cache overflow we occur rarely especially if agents + * beacon one time per second. Probably longer than + * laptops will be up. + */ + + + static + void wl_cache_store (int unit, int base, struct ether_header *eh, + struct mbuf *m) + { + struct ip *ip; + int i; + + /* InsertCacheItem holds index for adding the next cache entry + * AgeSequence is the counter for finding LRU entry + */ + + static int InsertCacheItem = 0; + static int AgeSequence = 0; + + /* The packet received may be a broadcast + * or multicast or a packet addressed to us. + * cache only IP packets ... + */ + + /* check if IP packet */ + if ( ntohs(eh->ether_type) != 0x800 ) { + return; + } + + /* check if broadcast or multicast packet. we toss + * unicast packets + */ + if ((eh->ether_dhost[0] & 1) == 0) { + return; + } + + /* use the mtod macro(in mbuf.h) + * to typecast m to struct ip * + */ + ip = mtod(m, struct ip *); + + /* do a linear search for a matching MAC address + * in the cache table + * . MAC address is 6 bytes, + * . var NextCacheItem holds total number of entries already cached + */ + for(i = 0; i < NextCacheItem; i++) { + if (! bcmp(eh->ether_shost ,w_sigcache[i].macsrc, 6 )) { + /* Match!, + * so we already have this entry, + * update the data, and LRU age + */ + break; + } + } + + /* did we break in the for loop? + * if yes, then overwrite a previously existing cache entry + */ + if (i < NextCacheItem ) { + InsertCacheItem = i; + } + /* else, have a new address entry,so + * add this new entry, + * if table full, then we need to replace LRU entry + */ + else { + /* check for space in cache table + * note: NextCacheItem also holds number of entries + * added in the cache table + */ + if ( NextCacheItem < MAXCACHEITEMS ) { + InsertCacheItem = NextCacheItem; + NextCacheItem++; + w_sigitems = NextCacheItem; + } + /* no space found, so find LRU entry & overwrite it + * update global var w_sigitem to hold the current no of + * entries in the cache + */ + else { + InsertCacheItem = OldestEntryNdx(); + } + } + + /* at this point var InsertCacheItem holds + * the index to be used for updating or adding + * for updating or adding the cache entry information + */ + + /* Populate the values here !! + * .ipsrc + * .macsrc + * .signal,silence,quality + */ + w_sigcache[InsertCacheItem].ipsrc = ip->ip_src.s_addr; + bcopy( eh->ether_shost ,w_sigcache[InsertCacheItem].macsrc, 6); + w_sigcache[InsertCacheItem].signal = wlpmmiread(base, MMC_SIGNAL_LVL) & 0x3f; + w_sigcache[InsertCacheItem].silence = wlpmmiread(base, MMC_SILENCE_LVL) & 0x3f; + w_sigcache[InsertCacheItem].quality = wlpmmiread(base, MMC_SIGN_QUAL) & 0x0f; + #ifdef KERNELTALK + /* note this will cause signal values to go to the kernel log. + * and is ONLY intended for debugging + */ + printf("signal %d silence %d quality %d\n", + w_sigcache[InsertCacheItem].signal, + w_sigcache[InsertCacheItem].silence, + w_sigcache[InsertCacheItem].quality); + #endif + + /* Assign an age counter to this entry. + * note: Lower value means Older entry + */ + + w_sigcache[InsertCacheItem].age = AgeSequence++; + + /* sanity checking on InsertCacheItem + */ + if (InsertCacheItem < 0 || InsertCacheItem >= MAXCACHEITEMS) { + printf("Error: wavelan signal cache: index insane %d!\n", + InsertCacheItem); + return ; + } + + /* check age modulation! + * before age counter overflows max int value!! + * check if need to reassign ages to avoid overflow + */ + if ( AgeSequence == MAX_AGE ) { + for (i = 0; i < NextCacheItem; i++) { + w_sigcache[ OldestEntryNdx() ].age = MAX_AGE+i; + } + + /* re-assign the ages finding newest entries */ + for (i = 0; i < NextCacheItem; i++) { + w_sigcache[i].age -= MAX_AGE; + } + /* after performing ageMODULATION + * the ages are in sequence from 1 to index of items in cache + * the next entry should get subsequent + * index value of NextCacheItem incremented by 1 + * as its age value + */ + AgeSequence = NextCacheItem; + } + } Index: PAO/sys/i386/isa/if_wlp.h diff -c /dev/null PAO/sys/i386/isa/if_wlp.h:1.1.8.1 *** /dev/null Fri Dec 25 10:50:58 1998 --- PAO/sys/i386/isa/if_wlp.h Sun Dec 6 07:47:29 1998 *************** *** 0 **** --- 1,145 ---- + /* + * HISTORY + * $Log: if_wlp.h,v $ + * Revision 1.1.8.1 1998/12/05 22:47:29 itojun + * sync with pao227 branch. + * right now, pao228 = r228 + (pao227 - r227) + (bsd-nomads 9735) + * + * confirmed that PAO_ALL is compileable **on 227 system**. need your checks. + * + * Revision 1.1.6.1 1998/07/27 11:27:36 kim + * Hidetoshi Kimura(kim@jp.freebsd.org) + * pao227 First Release under isa directory added files. + * PR: + * Reviewed by: + * Submitted by: + * Obtained from: + * + * Revision 1.1.4.1 1998/04/04 23:24:13 itojun + * PAO for FreeBSD 2.2.6-RELEASE. + * I dunno if it compiles or not... + * + * Submitted by: thasegawa@mta.biglobe.ne.jp + * + * Revision 1.1.2.1 1997/12/11 14:00:19 itojun + * PAO-971210 import. hope this works well... + * + * Obtained from: hosokawa + * + * Revision 1.1 1994/06/02 20:26:55 klemets + * Initial revision + * + * + */ + /* + * Definitions for the NCR WaveLAN PCMCIA driver. + * + * Copyright 1994, Anders Klemets + * All rights reserved. + * + * I permit including this code in the releases of FreeBSD. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The names of the authors may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _PCMCIA_IF_WLP_H + #define _PCMCIA_IF_WLP_H + + #include /* Definitions for the Intel chip */ + + /* WaveLAN host interface definitions */ + + #define LCCR(base) (base) /* LAN Controller Command Register */ + #define LCSR(base) (base) /* LAN Controller Status Register */ + #define HACR(base) (base+0x1) /* Host Adapter Command Register */ + #define HASR(base) (base+0x1) /* Host Adapter Status Register */ + #define PIORL(base) (base+0x2) /* Program I/O Register Low */ + #define RPLL(base) (base+0x2) /* Receive Pointer Latched Low */ + #define PIORH(base) (base+0x3) /* Program I/O Register High */ + #define RPLH(base) (base+0x3) /* Receive Pointer Latched High */ + #define PIOP(base) (base+0x4) /* Program I/O Port */ + #define MMR(base) (base+0x6) /* MMI Address Register */ + #define MMD(base) (base+0x7) /* MMI Data Register */ + + /* HACR bit definitions */ + + #define HACR_LOF (1 << 3) /* Lock Out Flag, toggle every 250ms */ + #define HACR_PWR_STAT (1 << 4) /* Power State, 1=active, 0=sleep */ + #define HACR_TX_DMA_RESET (1 << 5) /* Reset transmit DMA ptr on high */ + #define HACR_RX_DMA_RESET (1 << 6) /* Reset receive DMA ptr on high */ + #define HACR_ROM_WEN (1 << 7) /* EEPROM write enabled when true */ + + /* HASR bit definitions */ + + #define HASR_MMI_BUSY (1 << 2) /* MMI is busy when true */ + #define HASR_LOF (1 << 3) /* Lock out flag status */ + #define HASR_NO_CLK (1 << 4) /* active when modem not connected */ + + /* Miscellaneous bit definitions */ + + #define PIORH_SEL_TX (1 << 5) /* PIOR points to 0=rx/1=tx buffer */ + #define MMR_MMI_WR (1 << 0) /* Next MMI cycle is 0=read, 1=write */ + #define PIORH_MASK 0x1f /* only low 5 bits are significant */ + #define RPLH_MASK 0x1f /* only low 5 bits are significant */ + #define MMI_ADDR_MASK 0x7e /* Bits 1-6 of MMR are significant */ + + /* Attribute Memory map */ + + #ifndef WL_PCCARD + #define CIS_ADDR 0x0000 /* Card Information Satus Register */ + #define PSA_ADDR 0x0e00 /* Parameter Storage Area address */ + #define EEPROM_ADDR 0x1000 /* EEPROM address */ + #define COR_ADDR 0x4000 /* Configuration Option Register */ + #endif + + /* Configuration Option Register bit definitions */ + + #define COR_CONFIG (1 << 0) /* Config Index, 0 when unconfigured */ + #define COR_SW_RESET (1 << 7) /* Software Reset on true */ + + /* Local Memory map */ + + #define RX_BASE 0x0000 /* Receive memory, 8 kB */ + #define TX_BASE 0x2000 /* Transmit memory, 2 kB */ + #define UNUSED_BASE 0x2800 /* Unused, 22 kB */ + #define RX_SIZE (TX_BASE-RX_BASE) /* Size of receive area */ + #define RX_SIZE_SHIFT 6 /* Bits to shift in stop register */ + + #define MMI_WRITE(cmd,val) \ + while(inb(HASR(sp->base)) & HASR_MMI_BUSY) ; \ + outb(MMR(sp->base), ((cmd) << 1) | MMR_MMI_WR); \ + outb(MMD(sp->base), val); + + #ifndef WL_PCCARD + #define READ_PSA(addr) *(sp->psa + 2*(addr)) + #endif + + #define DSF_RUNNING 1 + + #define MOD_ENAL 1 + #define MOD_PROM 2 + + /* "flags" in config file */ + #define WLP_2400MHZ 0x01 /* use 2.4GHz band instead of 915MHz on + * WaveLAN PCMCIA */ + + #endif _PCMCIA_IF_WLP_H + + Index: PAO/sys/i386/isa/if_ze.c diff -c PAO/sys/i386/isa/if_ze.c:1.1.1.3 PAO/sys/i386/isa/if_ze.c:1.1.1.3.4.1 *** PAO/sys/i386/isa/if_ze.c:1.1.1.3 Fri Jul 24 19:17:52 1998 --- PAO/sys/i386/isa/if_ze.c Sun Dec 6 07:47:30 1998 *************** *** 39,45 **** /* * I doubled delay loops in this file because it is not enough for some * laptop machines' PCIC (especially, on my Chaplet ILFA 350 ^^;). ! * HOSOKAWA, Tatsumi */ /* * Very small patch for IBM Ethernet PCMCIA Card II and IBM ThinkPad230Cs. --- 39,45 ---- /* * I doubled delay loops in this file because it is not enough for some * laptop machines' PCIC (especially, on my Chaplet ILFA 350 ^^;). ! * HOSOKAWA, Tatsumi */ /* * Very small patch for IBM Ethernet PCMCIA Card II and IBM ThinkPad230Cs. Index: PAO/sys/i386/isa/if_zp.c diff -c PAO/sys/i386/isa/if_zp.c:1.1.1.2 PAO/sys/i386/isa/if_zp.c:1.1.1.2.6.1 *** PAO/sys/i386/isa/if_zp.c:1.1.1.2 Sun Apr 5 07:12:00 1998 --- PAO/sys/i386/isa/if_zp.c Sun Dec 6 07:47:32 1998 *************** *** 7,14 **** * (4) RT-Mach implementation on PCMCIA/ISA/EISA Etherlink III * by Seiji Murata * ! * Copyright (c) by HOSOKAWA, Tatsumi ! * Copyright (c) by Seiji Murata */ /* * Copyright (c) 1993 Herb Peyerl --- 7,14 ---- * (4) RT-Mach implementation on PCMCIA/ISA/EISA Etherlink III * by Seiji Murata * ! * Copyright (c) by HOSOKAWA, Tatsumi ! * Copyright (c) by Seiji Murata */ /* * Copyright (c) 1993 Herb Peyerl *************** *** 93,99 **** /* * I doubled delay loops in this file because it is not enough for some * laptop machines' PCIC (especially, on my Chaplet ILFA 350 ^^;). ! * HOSOKAWA, Tatsumi */ /* * Very small patch for IBM Ethernet PCMCIA Card II and IBM ThinkPad230Cs. --- 93,99 ---- /* * I doubled delay loops in this file because it is not enough for some * laptop machines' PCIC (especially, on my Chaplet ILFA 350 ^^;). ! * HOSOKAWA, Tatsumi */ /* * Very small patch for IBM Ethernet PCMCIA Card II and IBM ThinkPad230Cs. Index: PAO/sys/i386/isa/isa.c diff -c PAO/sys/i386/isa/isa.c:1.1.1.3 PAO/sys/i386/isa/isa.c:1.1.1.3.4.1 *** PAO/sys/i386/isa/isa.c:1.1.1.3 Fri Jul 24 19:17:55 1998 --- PAO/sys/i386/isa/isa.c Sun Dec 6 07:47:34 1998 *************** *** 54,61 **** --- 54,64 ---- #include #include #include + #include + #include #include #include + #include #include #include #include *************** *** 86,91 **** --- 89,97 ---- u_int intr_mask[ICU_LEN]; u_int* intr_mptr[ICU_LEN]; int intr_unit[ICU_LEN]; + static u_int intr_inuse; + + SYSCTL_INT(_machdep, CPU_INTRINUSE, intr_inuse, CTLFLAG_RD, &intr_inuse, 0, ""); static inthand_t *fastintr[ICU_LEN] = { &IDTVEC(fastintr0), &IDTVEC(fastintr1), *************** *** 495,500 **** --- 501,511 ---- /* icu vectors */ for (i = 0; i < ICU_LEN; i++) unregister_intr(i, (inthand2_t *)NULL); + intr_inuse = 0; + /* XXX hardcoded kludge! - should be automated */ + intr_inuse |= (1 << 2); /* master/slave connection IRQ*/ + intr_inuse |= (1 << 8); /* RTC */ + intr_inuse |= (1 << 13); /* FPU */ /* initialize 8259's */ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ *************** *** 1110,1115 **** --- 1121,1127 ---- intr_mptr[intr] = maskptr; intr_mask[intr] = mask | (1 << intr); intr_unit[intr] = unit; + intr_inuse |= (1 << intr); setidt(ICU_OFFSET + intr, flags & RI_FAST ? fastintr[intr] : slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); *************** *** 1159,1166 **** --- 1171,1289 ---- intr_mptr[intr] = NULL; intr_mask[intr] = HWI_MASK | SWI_MASK; intr_unit[intr] = intr; + intr_inuse &= ~(1 << intr); setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); write_eflags(ef); return (0); } + + static int + sysctl_machdep_checkio SYSCTL_HANDLER_ARGS + { + int *name = (int *)arg1; + u_int namelen = arg2; + int iobase, iorange; + struct isa_device *tmpdvp; + int status; + + if (namelen != 2) + return EINVAL; + iobase = name[0]; + iorange = name[1]; + + #define NOCONFLICT \ + (tmpdvp->id_alive == 0 || tmpdvp->id_alive == -1 \ + || iobase + iorange - 1 < tmpdvp->id_iobase \ + || tmpdvp->id_iobase + tmpdvp->id_alive - 1 < iobase) + + status = 0; + for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + #undef NOCONFLICT + + answer: + SYSCTL_OUT(req, &status, sizeof(status)); + return 0; + } + + SYSCTL_NODE(_machdep, CPU_CHECKIO, checkio, CTLFLAG_RD, + sysctl_machdep_checkio, ""); + + + static int + sysctl_machdep_checkmem SYSCTL_HANDLER_ARGS + { + int *name = (int *)arg1; + u_int namelen = arg2; + caddr_t membase; + int memrange; + struct isa_device *tmpdvp; + int status; + + if (namelen != 2) + return EINVAL; + membase = (caddr_t)name[0]; + memrange = name[1]; + + #define NOCONFLICT \ + (tmpdvp->id_msize == 0 || tmpdvp->id_msize == -1 \ + || KERNBASE + membase + memrange - 1 < tmpdvp->id_maddr \ + || tmpdvp->id_maddr + tmpdvp->id_msize - 1 < KERNBASE + membase) + + status = 0; + for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { + if (!NOCONFLICT) { + status = -1; + goto answer; + } + } + #undef NOCONFLICT + + answer: + SYSCTL_OUT(req, &status, sizeof(status)); + return 0; + } + + SYSCTL_NODE(_machdep, CPU_CHECKMEM, checkmem, CTLFLAG_RD, + sysctl_machdep_checkmem, ""); Index: PAO/sys/i386/isa/isa.h diff -c PAO/sys/i386/isa/isa.h:1.1.1.1 PAO/sys/i386/isa/isa.h:1.1.1.1.8.1 *** PAO/sys/i386/isa/isa.h:1.1.1.1 Thu Dec 11 22:36:59 1997 --- PAO/sys/i386/isa/isa.h Sun Dec 6 07:47:35 1998 *************** *** 124,129 **** --- 124,130 ---- #define IO_LPT1 0x378 /* Parallel Port #1 */ /* 0x380 - 0x3AA Open */ + #define IO_YEFDC 0x3A8 /* Libretto PCMCIA floppy */ #define IO_ASC8 0x3AB /* AmiScan addr.grp. 8 */ #define IO_MDA 0x3B0 /* Monochome Adapter */ Index: PAO/sys/i386/isa/joy.c diff -c PAO/sys/i386/isa/joy.c:1.1.1.2 PAO/sys/i386/isa/joy.c:1.1.1.2.6.1 *** PAO/sys/i386/isa/joy.c:1.1.1.2 Sun Apr 5 07:12:07 1998 --- PAO/sys/i386/isa/joy.c Sun Dec 6 07:47:37 1998 *************** *** 46,51 **** --- 46,64 ---- #include #include + #ifndef JOY_MODULE + #include "card.h" + #else + #define NCARD 0 + #endif + + #if NCARD > 0 + #include + #include + #include + #include + #endif + /* The game port can manage 4 buttons and 4 variable resistors (usually 2 * joysticks, each with 2 buttons and 2 pots.) via the port at address 0x201. * Getting the state of the buttons is done by reading the game port: *************** *** 97,102 **** --- 110,211 ---- static int get_tick __P((void)); + #if NCARD > 0 + /* + * PC-Card (PCMCIA) specific code. + */ + static int joy_card_intr(struct pccard_devinfo *); /* Interrupt handler */ + static void joy_card_unload(struct pccard_devinfo *); /* Disable driver */ + static void joy_card_suspend(struct pccard_devinfo *); /* Suspend driver */ + static int joy_card_init(struct pccard_devinfo *); /* init device */ + + static struct pccard_device joy_info = { + "joy", + joy_card_init, + joy_card_unload, + joy_card_intr, + /* joy_card_suspend, */ + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + /* XXX - Should this also include net_imask? */ + }; + + DATA_SET(pccarddrv_set, joy_info); + + static int pccard_mode[NJOY]; + /* + * Called when a power down is requested. Shuts down the + * device and configures the device as unavailable (but + * still loaded...). A resume is done by calling + * joyinit with first=0. This is called when the user suspends + * the system, or the APM code suspends the system. + */ + static void + joy_card_suspend(struct pccard_devinfo *devi) + { + printf("joy%d: suspending\n", devi->pd_unit); + } + + /* + * Initialize the device - called from Slot manager. + * If first is set, then check for the device's existence + * before initializing it. Once initialized, the device table may + * be set up. + */ + int + joy_card_init(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + + /* validate unit number. */ + if (unit >= NJOY) + return(ENODEV); + pccard_mode[unit] = 1; + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + if (joyprobe(&devi->isahd)==0) + return(ENXIO); + if (joyattach(&devi->isahd)==0) + return(ENXIO); + /* + * XXX TODO: + * If it was initialized before, the device structure + * should also be initialized. We should + * reset (and possibly restart) the hardware, but + * I am not sure of the best way to do this... + */ + return(0); + } + + /* + * joy_card_unload - unload the driver and clear the table. + * XXX TODO: + * This is usually called when the card is ejected, but + * can be caused by a modunload of a controller driver. + * The idea is to reset the driver's view of the device + * and ensure that any driver entry points such as + * read and write do not hang. + */ + static void + joy_card_unload(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + + pccard_mode[unit] = 0; + } + + /* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int + joy_card_intr(struct pccard_devinfo *devi) + { + return(1); + } + #endif /* NCARD > 0 */ static int joyprobe (struct isa_device *dev) Index: PAO/sys/i386/isa/kbdtables.h diff -c PAO/sys/i386/isa/kbdtables.h:1.1.1.4 PAO/sys/i386/isa/kbdtables.h:1.1.1.4.2.1 *** PAO/sys/i386/isa/kbdtables.h:1.1.1.4 Sat Dec 5 05:37:52 1998 --- PAO/sys/i386/isa/kbdtables.h Sun Dec 6 07:47:40 1998 *************** *** 30,35 **** --- 30,157 ---- #define SET8 0x80 /* set eight bit on */ + #ifdef NECMG + /* + * NEC Mobile Gear keymap by takemura@ca2.so-net.ne.jp + */ + #define NO_ACCENTCHARS + static keymap_t key_map = { 0x6c, /* NEC Mobile Gear keymap */ + /* alt + * scan cntrl alt alt cntrl + * code base shift cntrl shift alt shift cntrl shift spcl flgs + * --------------------------------------------------------------------------- + */ + /* sc=00 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, + /* sc=01 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, DBG, 0x1B, 0x02, 0x00, + /* sc=02 */ '1', '!', '!', '!', '1', '!', '!', '!', 0x00, 0x00, + /* sc=03 */ '2', '\"', 0x1A, 0x1A, '2', '@', 0x00, 0x00, 0x00, 0x00, + /* sc=04 */ '3', '#', 0x1B, 0x1B, '3', '#', 0x1B, 0x1B, 0x00, 0x00, + /* sc=05 */ '4', '$', 0x1C, 0x1C, '4', '$', 0x1C, 0x1C, 0x00, 0x00, + /* sc=06 */ '5', '%', 0x1D, 0x1D, '5', '%', 0x1D, 0x1D, 0x00, 0x00, + /* sc=07 */ '6', '&', 0x1E, 0x1E, '6', '^', 0x1E, 0x1E, 0x00, 0x00, + /* sc=08 */ '7', '\'', 0x1F, 0x1F, '7', '&', '&', '&', 0x00, 0x00, + /* sc=09 */ '8', '(', 0x7F, 0x7F, '8', '*', 0x08, 0x08, 0x00, 0x00, + /* sc=0a */ '9', ')', '9', '9', '9', '(', '(', '(', 0x00, 0x00, + /* sc=0b */ '0', NOP, '0', '0', '0', ')', ')', ')', 0x40, 0x00, + /* sc=0c */ '-', '=', '-', '-', '-', '_', 0x1F, 0x1F, 0x00, 0x00, + /* sc=0d */ '^', '`', 0x1E, 0x1E, '=', '+', '+', '+', 0x00, 0x00, + /* sc=0e */ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + /* sc=0f */ '\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t', 0x00, 0x00, + /* sc=10 */ 'q', 'Q', 0x11, 0x11, 'q', 'Q', 0x11, 0x11, 0x00, 0x01, + /* sc=11 */ 'w', 'W', 0x17, 0x17, 'w', 'W', 0x17, 0x17, 0x00, 0x01, + /* sc=12 */ 'e', 'E', 0x05, 0x05, 'e', 'E', 0x05, 0x05, 0x00, 0x01, + /* sc=13 */ 'r', 'R', 0x12, 0x12, 'r', 'R', 0x12, 0x12, 0x00, 0x01, + /* sc=14 */ 't', 'T', 0x14, 0x14, 't', 'T', 0x14, 0x14, 0x00, 0x01, + /* sc=15 */ 'y', 'Y', 0x19, 0x19, 'y', 'Y', 0x19, 0x19, 0x00, 0x01, + /* sc=16 */ 'u', 'U', 0x15, 0x15, 'u', 'U', 0x15, 0x15, 0x00, 0x01, + /* sc=17 */ 'i', 'I', 0x09, 0x09, 'i', 'I', 0x09, 0x09, 0x00, 0x01, + /* sc=18 */ 'o', 'O', 0x0F, 0x0F, 'o', 'O', 0x0F, 0x0F, 0x00, 0x01, + /* sc=19 */ 'p', 'P', 0x10, 0x10, 'p', 'P', 0x10, 0x10, 0x00, 0x01, + /* sc=1a */ '@', '~', 0x00, 0x00, '[', '{', 0x1B, 0x1B, 0x00, 0x00, + /* sc=1b */ '[', '{', 0x1B, 0x1B, ']', '}', 0x1D, 0x1D, 0x00, 0x00, + /* sc=1c */ '\r', '\r', '\n', '\n', '\r', '\r', '\n', '\n', 0x00, 0x00, + /* sc=1d */ LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, LCTR, 0xFF, 0x00, + /* sc=1e */ 'a', 'A', 0x01, 0x01, 'a', 'A', 0x01, 0x01, 0x00, 0x01, + /* sc=1f */ 's', 'S', 0x13, 0x13, 's', 'S', 0x13, 0x13, 0x00, 0x01, + /* sc=20 */ 'd', 'D', 0x04, 0x04, 'd', 'D', 0x04, 0x04, 0x00, 0x01, + /* sc=21 */ 'f', 'F', 0x06, 0x06, 'f', 'F', 0x06, 0x06, 0x00, 0x01, + /* sc=22 */ 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, 0x00, 0x01, + /* sc=23 */ 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, 0x00, 0x01, + /* sc=24 */ 'j', 'J', '\n', '\n', 'j', 'J', '\n', '\n', 0x00, 0x01, + /* sc=25 */ 'k', 'K', 0x0B, 0x0B, 'k', 'K', 0x0B, 0x0B, 0x00, 0x01, + /* sc=26 */ 'l', 'L', 0x0C, 0x0C, 'l', 'L', 0x0C, 0x0C, 0x00, 0x01, + /* sc=27 */ ';', '+', ';', ';', ';', ':', ';', ';', 0x00, 0x00, + /* sc=28 */ ':', '*', ':', ':', '\'', '\"', '\'', '\'', 0x00, 0x00, + /* sc=29 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, + /* sc=2a */ LSH, LSH, LSH, LSH, LSH, LSH, LSH, LSH, 0xFF, 0x00, + /* sc=2b */ '\\', '|', 0x1C, 0x1C, '\\', '|', 0x1C, 0x1C, 0x00, 0x00, + /* sc=2c */ 'z', 'Z', 0x1A, 0x1A, 'z', 'Z', 0x1A, 0x1A, 0x00, 0x01, + /* sc=2d */ 'x', 'X', 0x18, 0x18, 'x', 'X', 0x18, 0x18, 0x00, 0x01, + /* sc=2e */ 'c', 'C', 0x03, 0x03, 'c', 'C', 0x03, 0x03, 0x00, 0x01, + /* sc=2f */ 'v', 'V', 0x16, 0x16, 'v', 'V', 0x16, 0x16, 0x00, 0x01, + /* sc=30 */ 'b', 'B', 0x02, 0x02, 'b', 'B', 0x02, 0x02, 0x00, 0x01, + /* sc=31 */ 'n', 'N', 0x0E, 0x0E, 'n', 'N', 0x0E, 0x0E, 0x00, 0x01, + /* sc=32 */ 'm', 'M', 0x0D, 0x0D, 'm', 'M', 0x0D, 0x0D, 0x00, 0x01, + /* sc=33 */ ',', '<', NOP, NOP, ',', '<', NOP, NOP, 0x33, 0x00, + /* sc=34 */ '.', '>', NOP, NOP, '.', '>', NOP, NOP, 0x33, 0x00, + /* sc=35 */ '/', '?', NOP, NOP, '/', '?', NOP, NOP, 0x33, 0x00, + /* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00, + /* sc=37 */ F(52), '-', '-', '-', '-', '-', '-', '-', 0x80, 0x02, + /* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00, + /* sc=39 */ ' ', ' ', 0x00, ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00, + /* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00, + /* sc=3b */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, + /* sc=3c */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00, + /* sc=3d */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00, + /* sc=3e */ F( 3), F(15), F(27), F(39), S( 3), S(13), S( 3), S(13), 0xFF, 0x00, + /* sc=3f */ F( 4), F(16), F(28), F(40), S( 4), S(14), S( 4), S(14), 0xFF, 0x00, + /* sc=30 */ F( 5), F(17), F(29), F(41), S( 5), S(15), S( 5), S(15), 0xFF, 0x00, + /* sc=41 */ F( 6), F(18), F(30), F(42), S( 6), S(16), S( 6), S(16), 0xFF, 0x00, + /* sc=42 */ F( 7), F(19), F(31), F(43), S( 7), S( 7), S( 7), S( 7), 0xFF, 0x00, + /* sc=43 */ F( 8), F(20), F(32), F(44), S( 8), S( 8), S( 8), S( 8), 0xFF, 0x00, + /* sc=44 */ F( 9), F(21), F(33), F(45), S( 9), S( 9), S( 9), S( 9), 0xFF, 0x00, + /* sc=45 */ NLK, NLK, NLK, NLK, NLK, NLK, NLK, NLK, 0xFF, 0x00, + /* sc=46 */ F(10), F(22), F(34), F(46), S(10), S(10), S(10), S(10), 0xFF, 0x00, + /* sc=47 */ F(49), '7', '7', '7', '7', '7', '7', '7', 0x80, 0x02, + /* sc=48 */ F(50), '8', '8', '8', '8', '8', '8', '8', 0x80, 0x02, + /* sc=49 */ F(51), '9', '9', '9', '9', '9', '9', '9', 0x80, 0x02, + /* sc=4a */ F(52), '*', '*', '*', '*', '*', '*', '*', 0x80, 0x02, + /* sc=4b */ F(53), '4', '4', '4', '4', '4', '4', '4', 0x80, 0x02, + /* sc=4c */ F(54), '5', '5', '5', '5', '5', '5', '5', 0x80, 0x02, + /* sc=4d */ F(55), '6', '6', '6', '6', '6', '6', '6', 0x80, 0x02, + /* sc=4e */ F(56), '+', '+', '+', '+', '+', '+', '+', 0x80, 0x02, + /* sc=4f */ F(57), '1', '1', '1', '1', '1', '1', '1', 0x80, 0x02, + /* sc=50 */ F(58), '2', '2', '2', '2', '2', '2', '2', 0x80, 0x02, + /* sc=51 */ F(59), '3', '3', '3', '3', '3', '3', '3', 0x80, 0x02, + /* sc=52 */ F(60), '0', '0', '0', '0', '0', '0', '0', 0x80, 0x02, + /* sc=53 */ 0x7F, '.', '.', '.', '.', '.', RBT, RBT, 0x03, 0x02, + /* sc=54 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, + /* sc=55 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, + /* sc=56 */ NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, + /* sc=57 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, + /* sc=58 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, + /* sc=59 */ 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, + /* sc=5a */ NOP, '_', 0x1F, 0x1F, '\\', '|', 0x1C, 0x1C, 0x80, 0x00, + /* sc=5b */ '=', '=', '=', '=', '=', '=', '=', '=', 0x00, 0x00, + /* sc=5c */ SLK, NOP, DBG, NOP, NOP, NOP, NOP, NOP, 0xFF, 0x00, + /* sc=5d */ RALT, RALT, RALT, RALT, RALT, RALT, RALT, RALT, 0xFF, 0x00, + /* sc=5e */ '/', '/', '/', '/', '/', '/', '/', '/', 0x00, 0x00, + /* sc=5f */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, + /* sc=60 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, + /* sc=61 */ F(53), F(53), F(53), F(53), F(53), F(53), F(53), F(53), 0xFF, 0x00, + /* sc=62 */ F(55), F(55), F(55), F(55), F(55), F(55), F(55), F(55), 0xFF, 0x00, + /* sc=63 */ ',', ',', ',', ',', ',', ',', ',', ',', 0x00, 0x00, + /* sc=64 */ F(58), F(58), F(58), F(58), F(58), F(58), F(58), F(58), 0xFF, 0x00, + /* sc=65 */ ']', '}', 0x1D, 0x1D, '`', '~', '~', '~', 0x00, 0x00, + /* sc=66 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, + /* sc=67 */ F(61), F(61), F(61), F(61), F(61), F(61), RBT, F(61), 0xFF, 0x00, + /* sc=68 */ SLK, SLK, SLK, SLK, SLK, SLK, SLK, SLK, 0xFF, 0x00, + /* sc=69 */ F(62), F(62), F(62), F(62), F(62), F(62), F(62), F(62), 0xFF, 0x00, + /* sc=6a */ F(63), F(63), F(63), F(63), F(63), F(63), F(63), F(63), 0xFF, 0x00, + /* sc=6b */ F(64), F(64), F(64), F(64), F(64), F(64), F(64), F(64), 0xFF, 0x00, + }; + #endif + #ifdef PC98 #define NO_ACCENTCHARS /* PC-9801 keymap by kuribo@isl.melco.co.jp */ *************** *** 1130,1136 **** }; #endif ! #if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) && !defined(ISKEYMAP) && !defined(ESKEYMAP) && !defined(PC98) #define ISO_ACCENTCHARS static keymap_t key_map = { 0x6C, /* US iso8859 keymap */ /* alt --- 1252,1258 ---- }; #endif ! #if !defined(DKKEYMAP) && !defined(UKKEYMAP) && !defined(GRKEYMAP) && !defined(SWKEYMAP) && !defined(RUKEYMAP) && !defined(ISKEYMAP) && !defined(ESKEYMAP) && !defined(PC98) && !defined(NECMG) #define ISO_ACCENTCHARS static keymap_t key_map = { 0x6C, /* US iso8859 keymap */ /* alt Index: PAO/sys/i386/isa/nin.c diff -c /dev/null PAO/sys/i386/isa/nin.c:1.1.2.1 *** /dev/null Fri Dec 25 10:51:03 1998 --- PAO/sys/i386/isa/nin.c Wed Dec 23 03:29:46 1998 *************** *** 0 **** --- 1,3868 ---- + /* + * Copyright (c) 1998 WORKBIT + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY WORKBIT ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL WORKBIT BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + + /************************************************************************* + * + * Copyright (c) 1995-1998 Workbit Corporation + * + * Module Name: + * + * nin.c + * + * Abstract: + * + * Definitions for the Ninja SCSI-3 CARD + * + ****************************************************************************/ + + #include "nin.h" + + /*#define DBG 1 *//* for debug*/ + + + #define USE_INTENTRY + #define USE_IRQ_MASK + #define USE_DISCONECT + + + #include + #ifdef KERNEL /* don't laugh.. look for main() */ + + #include + #include + #include + #include + #include + #include + #include + + #include + #include + + #include + #include + #include + + #include + + + #endif /* KERNEL */ + #include + #include + #include + + #ifdef KERNEL + #include + #else /*KERNEL */ + #define NNIN 1 + #endif /*KERNEL */ + + + #define max(a,b) (((a) > (b)) ? (a) : (b)) + #define min(a,b) (((a) < (b)) ? (a) : (b)) + + /* #include "scsi.h" */ + + #define BASE_PORT 0x180 + #define NUMBR_PORTS 0x10 + #define BASE_WIDTH 0x10 + #define SCSI_PORT 0x0 + + /********************************************************/ + /* Input status bit definitions.*/ + /********************************************************/ + #define S_ATN 0x80 + #define S_SELECT 0x40 + + #define S_REQUEST 0x20 /* Request line from SCSI bus*/ + #define S_ACK 0x10 /* Acknowlege line from SCSI bus*/ + #define S_BUSY 0x08 /* Busy line from SCSI bus*/ + #define S_CD 0x04 /* Command/Data line from SCSI bus*/ + #define S_IO 0x02 /* Input/Output line from SCSI bus*/ + #define S_MESSAGE 0x01 /* Message line from SCSI bus*/ + + /********************************************************/ + /* Useful Bus Monitor status combinations.*/ + /********************************************************/ + #define BM_BUS_FREE 0 + #define BM_COMMAND ( S_BUSY | S_CD | S_REQUEST ) + #define BM_MESSAGE_IN ( S_BUSY | S_MESSAGE | S_IO | S_CD | S_REQUEST ) + #define BM_MESSAGE_OUT ( S_BUSY | S_MESSAGE | S_CD | S_REQUEST ) + #define BM_DATA_IN ( S_BUSY | S_IO | S_REQUEST ) + #define BM_DATA_OUT ( S_BUSY | S_REQUEST ) + #define BM_STATUS ( S_BUSY | S_IO | S_CD | S_REQUEST ) + #define BM_RESELECT ( S_SELECT | S_IO ) + + #define BP_COMMAND ( S_CD ) + #define BP_MESSAGE_IN ( S_MESSAGE | S_IO | S_CD ) + #define BP_MESSAGE_OUT ( S_MESSAGE | S_CD ) + #define BP_DATA_IN ( S_IO ) + #define BP_DATA_OUT ( 0 ) + #define BP_STATUS ( S_IO | S_CD ) + + + /********************************************************/ + /* SCSI bus status codes.*/ + /********************************************************/ + /* Status Byte in scsiall.h*/ + #define SCSI_CONDITION_MET 0x04 + #define SCSI_INTERMEDIATE_COND_MET 0x14 + #define SCSI_RESERVATION_CONFLICT 0x18 + #define SCSI_COMMAND_TERMINATED 0x22 + + + #define MSG_IDENTIFYFLAG_WITH_DISCON 0XC0 + + /********************************************************/ + /* SCSI Extended Message Lengths*/ + /********************************************************/ + + #define SCSIMESS_MODIFY_DATA_LENGTH 5 + #define SCSIMESS_SYNCH_DATA_LENGTH 3 + #define SCSIMESS_WIDE_DATA_LENGTH 2 + + /********************************************************/ + /* SCSI Extended Message operation codes*/ + /********************************************************/ + + #define SCSIMESS_MODIFY_DATA_POINTER 0X00 + #define SCSIMESS_SYNCHRONOUS_DATA_REQ 0X01 + #define SCSIMESS_WIDE_DATA_REQUEST 0X03 + + typedef struct _SCSI_EXMSG { + u_char InitialMessageCode; + u_char MessageLength; + u_char MessageType; + union _EXTENDED_ARGUMENTS { + struct { + u_char modifier[4]; + } MODIFY; + struct { + u_char TransferPeriod; + u_char ReqAckOffset; + } SYNCS; + struct{ + u_char Width; + } WIDE; + }ExArg; + }SCSI_EXMSG, *PSCSI_EXMSG; + + + /********************************************************/ + /* Status mask for bus phase.*/ + /********************************************************/ + #define S_PHASE_MASK ((u_char) 0x3f) + + + /********************************************************/ + /* SCSI source identifier for host system.*/ + /********************************************************/ + #define SCSI_INITIATOR_ID 7 + #define SCSI_IDT_VECTOR 5 + + /********************************************************/ + /* Various timeout values (in microseconds).*/ + /********************************************************/ + #define REQUEST_SPIN_WAIT 40000 /* Wait for target to assert REQUEST*/ + #define RESET_HOLD_TIME 25 /* Time to hold RESET line to reset bus*/ + #define RESET_RECOVER_TIME 2500000 + #define BUS_FREE_DELAY 100000 /* Wait for BUS_FREE condition*/ + + /********************************************************/ + /* Number of adapters this driver will support.*/ + /********************************************************/ + #define MAX_ADAPTERS 1 + + /********************************************************/ + /* Limit transfer length to 64 Kbytes*/ + /* */ + #define MAX_TRANSFER_LENGTH ( 64 * 1024 ) + + #ifdef DBG + long INT_POLL_SEL = 10; + long INT_POLL_IRQ = 10; + #else + #define INT_POLL_SEL 10 + #define INT_POLL_IRQ 10 + #endif + + typedef struct _IRQ_STATUS { /* #0*/ + u_char ScsiIrqStatus : 1; + u_char ExtIrqStatus : 1; + u_char TimerIrqStatus : 1; + u_char FifoIrqStatus : 1; + u_char ScsiIrqMask : 1; + u_char ExtIrqMask : 1; + u_char TimerIrqMask : 1; + u_char FifoIrqMask : 1; + } IRQ_STATUS, *PIRQ_STATUS; + + typedef struct _IRQ_CONTROLP { /* #0*/ + u_char ReselctIrqClear : 1; + u_char PhaseChgIrqClear : 1; + u_char TimerIrqClear : 1; + u_char FifoIrqClear : 1; + u_char ScsiIrqMask : 1; + u_char ExtIrqMask : 1; + u_char TimerIrqMask : 1; + u_char FifoIrqMask : 1; + } IRQ_CONTROLP, *PIRQ_CONTROLP; + + typedef struct _IF_SELECT { /* #1*/ + u_char IFSelect : 1; + u_char Reserved3 : 1; + u_char RegSelect : 1; + u_char Reserved2 : 5; + } IF_SELECT, *PIF_SELECT; + + typedef struct _FIFO_STATUS { /* #1*/ + u_char ChipRev : 4; + u_char ChipId : 3; + u_char FifoFullEmpty : 1; + } FIFO_STATUS, *PFIFO_STATUS; + + typedef struct _EXT_BUS_CONTROL { /* index 10h*/ + u_char Reserved0 : 4; + u_char IOMapConfigration : 1; + u_char ExrdyContrl : 1; + u_char IrqLevel : 1; + u_char Reserved1 : 1; + } EXT_BUS_CONTROL, *PEXT_BUS_CONTROL; + + typedef struct CLOCK_DIV { /* index 11h*/ + u_char ClkDivider : 2; + u_char Reserved6 : 6; + } CLOCK_DIV, *PCLOCK_DIV; + + typedef struct _TermPwrControl { /* index 13*/ + u_char TermPowerOn : 1; + u_char Reserved7 : 7; + } TermPwrControl, *PTermPwrControl; + + typedef struct _SCSI_IRQ_MODE { /* index 15*/ + u_char ScsiPhaseChangeEi : 1; + u_char Reserved8 : 3; + u_char ReselectIrqEi : 1; + u_char FifoIrqEi : 1; + u_char ScsiResetIrqEi : 1; + u_char Reserved75 : 1; + } SCSI_IRQ_MODE, *PSCSI_IRQ_MODE; + + typedef struct _IRQ_PHASE_SENSE { /* index 16*/ + u_char LatchMSG : 1; + u_char LatchI_O : 1; + u_char LatchC_D : 1; + u_char LatchBusFree : 1; + u_char PhaseChgIrq : 1; + u_char ReselectIrq : 1; + u_char FifoIrq : 1; + u_char ScsiResetIrq : 1; + } IRQ_PHASE_SENSE, *PIRQ_PHASE_SENSE; + + typedef struct SCSI_BUS_CONTROL { /* index 18*/ + u_char ScsiSel : 1; + u_char ScsiRst : 1; + u_char ScsiDataOutEnb : 1; + u_char ScsiATN : 1; + u_char ScsiACK : 1; + u_char ScsiBSY : 1; + u_char AutoDirection : 1; + u_char AckEnb : 1; + } SCSI_BUS_CONTROL, *PSCSI_BUS_CONTROL; + + typedef struct _SCSI_BUS_MONITOR { /* index 19*/ + u_char Scsi_MSG : 1; + u_char Scsi_I_O : 1; + u_char Scsi_C_D : 1; + u_char Scsi_BSY : 1; + u_char Scsi_ACK : 1; + u_char Scsi_REQ : 1; + u_char Scsi_SEL : 1; + u_char Scsi_ATN : 1; + } SCSI_BUS_MONITOR, *PSCSI_BUS_MONITOR; + + typedef struct _SET_ARBIT { /* index 1a*/ + u_char ArbitGo : 1; + u_char ArbitFlagClear : 1; + u_char Reserved10 : 6; + } SET_ARBIT,*PSET_ARBIT; + + typedef struct _ARBIT_STATUS { /* index 1a*/ + u_char ArbitGoStatus : 1; + u_char ArbitWin : 1; + u_char ArbitFail : 1; + u_char ReselectFlag : 1; + u_char Reserved11 : 4; + } ARBIT_STATUS, *PARBIT_STATUS; + + typedef struct _PARITY_CONTROL { /* index 1b*/ + u_char ParityCheckEnable : 1; + u_char ParityErrorClear : 1; + u_char Reserved12 : 6; + } PARITY_CONTROL, *PPARITY_CONTROL; + + typedef struct _PARITY_STATUS { /* index 1b*/ + u_char Reserved15 : 1; /* same as PARITY_CONTROL*/ + u_char ParityError : 1; + u_char Reserved14 : 2; + u_char ReadSource : 2; + u_char Reserved13 : 2; + } PARITY_STATUS, *PPARITY_STATUS; + + typedef struct _COMMAND_CONTROL { /* index 1c*/ + u_char ClrCommandPointer : 1; + u_char AutoCommandGo : 1; + u_char Reserved16 : 6; + } COMMAND_CONTROL, *PCOMMAND_CONTROL; + + typedef struct _POINTER_CLEAR { /* index 1e*/ + u_char PointerClear : 1; + u_char AckCounterClear : 1; + u_char ReqCounterClear : 1; + u_char HostCounterClear : 1; + u_char ReadSourceSet : 2; + u_char Reserved17 : 2; + } POINTER_CLEAR, *PPOINTER_CLEAR; + + typedef struct _TRANSFER_MODE { /* index 20*/ + u_char MemMap8 : 1; + u_char MemMap16_32 : 1; + u_char AdrData24 : 1; + u_char AdrData32 : 1; + u_char IO8 : 1; + u_char IO16_32 : 1; + u_char TransferGo : 1; + u_char FifoTest_Braind : 1; + } TRANSFER_MODE, *PTRANSFER_MODE; + + typedef struct _SYNC_REG { /* index 21*/ + u_char SyncOffset : 4; + u_char SyncPeriod : 4; + } SYNC_REG, *PSYNC_REG; + + + typedef struct _SCAM_CONTROL { /* index 24*/ + u_char ScamMSG : 1; + u_char ScamI_O : 1; + u_char ScamC_D : 1; + u_char ScamBSY : 1; + u_char ScamSEL : 1; + u_char ScamXferOn : 1; + u_char Reserved18 : 2; + } SCAM_CONTROL, *PSCAM_CONTROL; + + typedef struct _OTHER_CONTROL { /* index 26*/ + u_char TplRomWriteEnable : 1; + u_char TermPwrOut : 1; + u_char TermPwrSence : 1; + u_char Reserved19 : 5; + } OTHER_CONTROL, *POTHER_CONTROL; + + typedef struct _ACK_WIDTH { /* index 27*/ + u_char AckPulse : 2; + u_char Reserved20 : 6; + } ACK_WIDTH, *PACK_WIDTH; + + typedef struct _CHECK_SUM_CONTROL { /* index 2c*/ + u_char CheckSumClear : 1; + u_char ReadPointerClear : 1; + u_char Reserved21 : 6; + } CHECK_SUM_CONTROL, *PCHECK_SUM_CONTROL; + + #define IN + #define OUT + + #define IRQCONTROL 0 + #define IRQSTATUS 0 + #define IFSELECT 1 + #define FIFOSTATUS 0x1 + #define INDEXREG 0x2 + #define DATAREG 0x3 + #define FIFODATA 0x4 + #define FIFODATA1 0x5 + #define FIFODATA2 0x6 + #define FIFODATA3 0x7 + + #define WFIFODATA 0x4 + #define EXTBUSCTRL 0x10 + #define CLOCKDIV 0x11 + + #define TERMPWRCTRL 0x13 + + #define SCSIIRQMODE 0x15 + #define IRQPHASESENCE 0x16 + #define TIMERCOUNT 0x17 + #define SCSIBUSCTRL 0x18 + #define SCSIBUSMON 0x19 + + #define SETARBIT 0x1A + #define ARBITSTATUS 0x1A + + #define PARITYCTRL 0x1B + #define PARITYSTATUS 0x1B + + #define COMMANDCTRL 0x1C + #define RESELECTID 0x1C + + #define COMMANDDATA 0x1D + + #define POINTERCLR 0x1E + #define TRANSFERCOUNT 0x1E + + /* #define Reserved3*/ + #define TRANSFERMODE 0x20 + #define SYNCREG 0x21 + #define SCSIDATALATCH 0x22 + #define SCSIDATAIN 0x22 + #define SCSIDATAWITHACK 0x23 + #define SCAMCONTROL 0x24 + #define SCAMSTATUS 0x24 + #define SCAMDATA 0x25 + #define OTHERCONTROL 0x26 + #define ACKWIDTH 0x27 + #define CLRTESTPNT 0x28 + #define ACKCNTLD 0x29 + #define REQCNTLD 0x2A + #define HSTCNTLD 0x2B + #define CHECKSUM 0x2C + + + + + #define SCSI_IRQ_CONTROL(BASE,VALUE) \ + outb((BASE+IRQCONTROL), VALUE) + + #define SCSI_IRQ_MONITOR(BASE) \ + inb(BASE+IRQCONTROL) + + #define SCSI_IF_SELECT(BASE, VALUE) \ + outb((BASE+IFSELECT), VALUE) + + #define SCSI_FIFO_STATUS(BASE) \ + inb((BASE+FIFOSTATUS)) + + #define SCSI_READ_FIFO(BASE,BUFFER,COUNT) \ + insb((BASE+FIFODATA), (u_char *)BUFFER, COUNT) + + #define SCSI_WRITE_FIFO(BASE,BUFFER,COUNT) \ + outsb((BASE+FIFODATA), (u_char *)BUFFER, COUNT) + + #define SCSI_READ_FIFOW(BASE,BUFFER,COUNT) \ + insw((BASE+WFIFODATA), (u_int32_t *)BUFFER, (COUNT >> 1)) + + #define SCSI_WRITE_FIFOW(BASE,BUFFER,COUNT) \ + outsw((BASE+WFIFODATA ), (u_int32_t *)BUFFER, (COUNT >> 1)) + + #define SCSI_READ_FIFOD(BASE,BUFFER,COUNT) \ + insl((BASE+WFIFODATA), BUFFER, (COUNT >> 2)) + + #define SCSI_WRITE_FIFOD(BASE,BUFFER,COUNT) \ + outsl((BASE+WFIFODATA ), BUFFER, (COUNT >> 2)) + + #define SCSI_READ(ChipAddr,Register) ( \ + outb(ChipAddr+INDEXREG,Register),\ + inb(ChipAddr+DATAREG)\ + ) + + #define SCSI_WRITE(ChipAddr,Register,Value) { \ + outb(ChipAddr+INDEXREG,Register),\ + outb(ChipAddr+DATAREG,Value);\ + } + + + #define READ_XFER_CNT 512 + #define WRITE_BURST_CNT 512 /*64*/ + #define WRITE_SPOT_CNT 512 + + #define ASYNCHRONOUS_OFFSET 0 + #define ASYNCHRONOUS_PERIOD 0 + #define SYNCHRONOUS_OFFSET 15 + + #ifdef ULTRA + #define SYNCHRONOUS_PERIOD 0x0c + #else + #define SYNCHRONOUS_PERIOD 0x19 + #endif + + #define SYNCHRONOUS_PERIOD_10M 0x19 + #define SYNCHRONOUS_PERIOD_20M 0x0c + + typedef struct _SYNC_TABLE { + u_char StartPeriod; + u_char EndPeriod; + u_char TransferPeriod; + u_char AckWidth; + } SYNC_TABLE, *PSYNC_TABLE; + + #ifndef NT_INST + /* for PC CARD*/ + typedef struct _PWRENTRY { + u_char PowerLevel; + u_char ValidSignals; + } PWRENTRY; + + + + typedef struct _ACHARTBL { + char AdpCaps; + long ActiveHigh; + long ActiveLow; + } ACHARTBL; + + typedef struct _AINQADAPTOR { + char wBufferLength; + char wDataLength; + ACHARTBL CharTable; + char wNumPwrEntries; + PWRENTRY PwrEntry; + } AINQADAPTOR; + #endif + + typedef struct _SG_TABLE { + u_long BlockCount; + u_long BufferAddress; + } SG_TABLE, *PSG_TABLE; + + typedef struct _FIFO_TEST { + u_char XferMode; + u_char Rate; + } FIFO_TEST; + typedef FIFO_TEST *PFIFO_TEST; + typedef struct _FAST_MODE { + u_char XferMode; + u_char Rate; + u_char PcicTiming; + u_char MemorySpeed; + } FAST_MODE; + typedef FAST_MODE *PFAST_MODE; + + + + /********************************************************/ + /* Logical Unit states.*/ + /********************************************************/ + typedef enum _SCSI_STATE { + SC_UNDETERMINED, + SC_SELECT, + SC_COMMAND, + SC_DATA, + SC_STATUS, + SC_MSG_IN, + SC_MSG_OUT, + SC_COMPLETE, + SC_COMPLETE_OK, + SC_BUSFREE, + SC_DISCONNECT, + SC_RESELECT + } SCSI_STATE, *PSCSI_STATE; + + /* #pragma pack(4) */ + + /********************************************************/ + /* Logical Unit extension*/ + /********************************************************/ + typedef struct _SPECIFIC_LU_EXTENSION { + SCSI_STATE LuState; /* State information.*/ + char *SavedDataPointer; /* Current data pointer.*/ + u_long SavedDataLength; /* Current data lenght.*/ + + struct scsi_xfer *ActiveLuRequest; /* Active Srb for this LUN.*/ + + u_long PhaseWaitCounter; + u_long TransferedLength; + u_long AckCounter; + u_long HostCounter; + + void (*pXferRead)__P(( u_int,char *Buffer, size_t Length)); + void (*pXferWrite)__P(( u_int, char *Buffer, size_t Length)); + + /* SG_TABLE SG_LIST[18]; */ + u_long SG_Count; + } SPECIFIC_LU_EXTENSION, *PSPECIFIC_LU_EXTENSION; + + /********************************************************/ + /*define adapter type*/ + /********************************************************/ + #define OPT_NON_DISCONECT 0x0001 + #define OPT_TUNEUP_DI 0x0002 + #define OPT_PCIC_SPEED 0x0004 + #define OPT_MMIO_SPEED 0x0008 + #define OPT_NO_ATN 0x0010 + + /********************************************************/ + /* specific per target controller information.*/ + /********************************************************/ + typedef struct _SPECIFIC_TARGET_EXTENSION { + u_char TargetFlags; + u_char SynchronousPeriod; + u_char SynchronousOffset; + u_char AckWidth; + } SPECIFIC_TARGET_EXTENSION, *PSPECIFIC_TARGET_EXTENSION; + + + /********************************************************/ + /* Define target controller specific flags.*/ + /********************************************************/ + #define PD_SYNCHRONOUS_NEGOTIATION_DONE 0x0001 + #define PD_DO_NOT_NEGOTIATE 0x0002 + #define PD_SYNCHRONOUS_TRANSFER_SENT 0X0004 + + #define PD_SYNCHRONOUS_TRANSFER_SENT 0X0004 + + #ifdef ULTRA + static SYNC_TABLE SyncTable[] = {{0x0c,0x0c,0x1,0}, /* 20MB 50ns*/ + {0x19,0x19,0x3,1}, /* 10MB 100ns*/ + {0x1a,0x25,0x5,2}, /* 7.5MB 150ns*/ + {0x26,0x32,0x7,3}}; /* 5MB 200ns*/ + #define SYNC_TABLE_MAX 4 + #else + static SYNC_TABLE SyncTable[] = {{0x19,0x19,0x1,0}, /* 10MB 100ns*/ + {0x1a,0x25,0x2,0}, /* 7.5MB 150ns*/ + {0x26,0x32,0x3,1}}; /* 5MB 200ns*/ + #define SYNC_TABLE_MAX 3 + #endif + + + /* ----- OREASAMA ---------------------------------------------------*/ + #if DBG + /********************************************************/ + /* Globals and externals used for debugging.*/ + /********************************************************/ + + /********************************************************/ + /* Ns3Debug affects which debug prints are enabled:*/ + /********************************************************/ + /* 0x001 Arbitration and selection*/ + /* 0x002 Command, status*/ + /* 0x004 Data transfer*/ + /* 0x008 Message in*/ + /* 0x010 Miniport entry points and completion*/ + /* 0x020 Initialization and interrupt*/ + /* 0x040 StatusCheck and WaitForRequest*/ + /* 0x080 Control register manipulation*/ + /* 0x100 Completion*/ + /* 0x200 Phase info*/ + /* 0x400 Temporary*/ + /* 0x800 Panic*/ + /********************************************************/ + + /* ORESAMA u_long Ns3Debug = ( 0x7f );*/ + u_long Ns3Debug = ( 0xfff );/* ORESAMA MUST DELETE AFTER DEBUG*/ + #define Ns3DebugPrint(MASK, ARGS) \ + if (MASK & Ns3Debug) { \ + printf ARGS; \ + } + #else + #define Ns3DebugPrint(MASK, ARGS) + #endif + + + /********************************************************/ + /* Device extension*/ + /********************************************************/ + struct _SPECIFIC_DEVICE_EXTENSION; + typedef struct _SPECIFIC_DEVICE_EXTENSION nin_softc, *pnin_softc; + + /*typedef struct _SPECIFIC_DEVICE_EXTENSION */ + struct _SPECIFIC_DEVICE_EXTENSION + { + + SCSI_STATE ScsiState; + char *CurDataPointer; /* Current pointer for active LUN.*/ + u_long CurDataLength; /* Bytes left to xfer to this LUN.*/ + PSPECIFIC_LU_EXTENSION ActiveLogicalUnit; /* Currently active LUN.*/ + u_char PathId; + boolean InterruptPending; /* Waiting for interrupt.*/ + boolean DmaPending; /* Waiting for DMA setup.*/ + u_char DeviceType[8]; /* inquiry data save*/ + SPECIFIC_TARGET_EXTENSION TargetState[8]; + u_char TimerCycle; + u_char TimerCount; + u_char TransferMode; + boolean Write24BitEnable; + u_char MessageBuffer[8]; + u_long MessageCount; + u_char Pcic3a[6]; + + u_long SmitBuffer; + u_char TargetId; + u_char TargetLun; /* LUN for reselection*/ + u_char IrqMaskData; + u_char ScsiPrePhase; + u_short AdapterOption; + + void (*pXferRead)__P(( u_int,char *Buffer, size_t Length)); + void (*pXferWrite)__P(( u_int, char *Buffer, size_t Length)); + + FIFO_TEST CanTransMode[6]; /* can transfer-mode*/ + boolean IntWait; /* wait in int-routine?*/ + boolean ScsiCable; /* funny cable ? or FifoTest all NG*/ + u_long SSEntry; /* Socket Service Entry Point*/ + u_char WindowHandle; /* Socket memory-win-handle*/ + u_char PcicSpeed[2]; + #ifdef ULTRA + u_char SynchronousPeriod; + #endif + + struct scsi_link sc_link; /* prototype for subdevs 0414 */ + boolean gone; + int BaseAddress; /* Port address of adapter.*/ + int slot; /* Slot number (slot.h)*/ + int PcicSlot; /* Slot number (slot.h)*/ + int unit; + + }; + + int ninja3_precommand( + PSPECIFIC_LU_EXTENSION *luExt, + pnin_softc devExt, + struct scsi_xfer * Srb); + int ninja3_queuecommand( + struct scsi_xfer * cmd, + void (*done) (struct scsi_xfer *)); + + u_long Ns3FindAdapter(int unit); + boolean Ns3Initialize(int unit); + u_char Ns3FifoTest( int unit,IN PFIFO_TEST pTestMode); + void Ns3ResetScsiBus( pnin_softc DevExt ); + void Ns3MakeTestPat ( IN int unit, + IN u_short TestPat, + IN u_short * TestSave, + IN u_short * wTestSum, + IN u_char * bTestSum); + + void Ns3PcicTimingRest( int unit ); + void Ns3PcicTimingSave( int unit ); + PSPECIFIC_LU_EXTENSION + ScsiPortGetLogicalUnit(u_int8_t TargetId,u_int8_t Lun); + void ScsiPortFreeLogicalUnit(u_int8_t TargetId,u_int8_t Lun); + void Ns3StartExecution( + IN pnin_softc DevExt, + IN PSPECIFIC_LU_EXTENSION LuExtension, + IN struct scsi_xfer *Srb + ); + void Ns3IrqPolling ( int unit ); + /*void ninintr( int unit );*/ + boolean Ns3Select( IN pnin_softc DevExt , + struct scsi_xfer *srb); + void nin_done( IN pnin_softc DevExt, + IN int err_code ); + void Ns3SetTransferMode( IN pnin_softc DevExt ); + void Ns3RunPhase( IN pnin_softc DevExt, + IN IRQ_PHASE_SENSE IrqPhase ); + void Ns3DataInPhase( IN pnin_softc DevExt ); + void Ns3DataOutPhase( IN pnin_softc DevExt ); + + void Ns3SendCDB( IN pnin_softc DevExt ); + void Ns3MessageOut( IN pnin_softc DevExt ); + void Ns3MessageIn( IN pnin_softc DevExt ); + void Ns3Status( IN pnin_softc DevExt ); + boolean Ns3WaitForAckOff( pnin_softc DevExt ); + boolean Ns3WaitForReqOff( pnin_softc DevExt ); + + + void pio8_datain (IN u_int, char * ,size_t ); + void pio8_dataout (IN u_int, char * ,size_t ); + void pio32_datain (IN u_int, char * ,size_t ); + /* + void pio32_dataout (IN int DevExt , + u_long Buffer, + u_long Length ); + */ + void pio32_dataout (IN u_int BaseAddress , + char *Buffer, + size_t Length ); + + + + u_long read_ack_count ( IN pnin_softc DevExt ); + void Ns3BurstRead( IN pnin_softc DevExt ); + void Ns3BurstWrite( IN pnin_softc DevExt ); + void Ns3SpotRead ( IN pnin_softc DevExt ); + void Ns3SpotWrite ( IN pnin_softc DevExt ); + void Ns3SlowRead ( IN pnin_softc DevExt ); + void Ns3SlowWrite ( IN pnin_softc DevExt ); + + boolean Ns3ProcessReselection( IN pnin_softc DevExt ); + boolean Ns3MessageDecode( IN pnin_softc DevExt ); + + boolean Ns3DecodeSynchronousRequest( + IN pnin_softc DevExt, + PSPECIFIC_TARGET_EXTENSION TargetState, + IN u_char TargetID, + IN boolean ResponseExpected ); + + int nin_attach(struct isa_device *dev); + int nin_probe(struct isa_device *dev); + static int32_t nin_scsi_cmd __P((struct scsi_xfer *)); + static void nin_minphys(struct buf *bp); + static u_int32_t nin_adapter_info(int unit); + #ifdef SCSI_DETACH + static void nin_detach(struct isa_device *dev); + #endif + static nin_softc nin_data[NNIN]; + + #ifdef KERNEL + static struct scsi_adapter nin_switch = + { + nin_scsi_cmd, + nin_minphys, + 0, + 0, + nin_adapter_info, + "nin", + { 0, 0 } + }; + + /* the below structure is so we have a default dev struct for out link struct */ + static struct scsi_device nin_dev = + { + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + "nin", + 0, + { 0, 0 } + }; + + struct isa_driver nindriver = + { + nin_probe, + nin_attach, + "nin" + }; + + static u_int32_t TestPat[] = + { 0,0xffff,0x55aa,0xaa55,0x0011,0xffee,0x0001,0x00ff}; + + + static PSPECIFIC_LU_EXTENSION table[8][10]; + static u_char TestLoad[64]; + static u_char TestSave[64]; + + static FIFO_TEST DefaultOk[6] = { { 0x4,0}, /* 24bit*/ + { 0x2,0}, /* Mem32*/ + { 0x20,0}, /* IO32*/ + { 0x1,0}, /* MEM8*/ + { 0x10,0}, /* IO8*/ + { 0,0}}; /* test priority */ + static FIFO_TEST FifoTestResult[3][4][6]; + FAST_MODE FastestMode[4*3*6]; + + + #endif /* KERNEL */ + + /*------------------------------------------------------------------------*/ + + #include "card.h" + #if NCARD > 0 + #include + #include + #include + #include + + /* + * PC-Card (PCMCIA) specific code. + */ + static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ + static void nin_unload(struct pccard_devinfo *); /* Disable driver */ + static void nin_suspend(struct pccard_devinfo *); /* Suspend driver */ + static int nin_crdinit(struct pccard_devinfo *); /* init device */ + + static struct pccard_device pcc_nin_info = { + "nin", + nin_crdinit, /* attach probe */ + nin_unload, /* */ + /* nin_suspend,*/ /* */ + card_intr, /* interrupt*/ + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + }; + DATA_SET(pccarddrv_set, pcc_nin_info); + + #if 0 + /* + * Called when a power down is requested. Shuts down the + * device and configures the device as unavailable (but + * still loaded...). A resume is done by calling + * wlpcrdinit with first=0. This is called when the user suspends + * the system, or the APM code suspends the system. + */ + static void + nin_suspend(struct pccard_devinfo *dp) + { + pnin_softc sc = &nin_data[dp->isahd.id_unit]; + + Ns3DebugPrint(0x10,("nin%d: suspending\n", dp->isahd.id_unit)); + sc->gone = 1; + } + #endif /* 0 */ + + + /* + * Initialize the device + */ + static int + nin_crdinit(struct pccard_devinfo *dp) + { + /* struct nin_softc *sc = &nin_softc[dp->isahd.id_unit]; */ + pnin_softc sc = &nin_data[dp->isahd.id_unit]; + + /* validate unit number. */ + { /* if (first == 0) resume*/ + /* unit-num is max(NNIN) -> end*/ + if (dp->isahd.id_unit >= NNIN) { + Ns3DebugPrint(0x10,("nin_crdinit:ENODEV\n")); /* ORE*/ + return(ENODEV); + } + + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + sc->gone = 0; + /* Set slot-num for PCIC*/ + sc->PcicSlot = dp->slt->slotnum; + if (nin_probe(&dp->isahd)==0){ + Ns3DebugPrint(0x10,("nin_crdinit:ENXIO\n")); + return(ENXIO); + } + + if (nin_attach(&dp->isahd)==0) { + Ns3DebugPrint(0x10,("nin_crdinit:ENXIO\n")); + return(ENXIO); + } + } + /* + * XXX TODO: + * If it was initialized before, the device structure + * should also be initialized. We should + * reset (and possibly restart) the hardware, but + * I am not sure of the best way to do this... + */ + return(0); + } + + /* + * nin_unload - unload the driver and clear the table. + * XXX TODO: + */ + static void + nin_unload(struct pccard_devinfo *dp) + { + /* struct nin_softc *sc = &nin_softc[dp->isahd.id_unit]; */ + pnin_softc sc = &nin_data[dp->isahd.id_unit]; + + sc->gone = 1; + Ns3DebugPrint(0x10,("nin%d: unload\n", dp->isahd.id_unit)); + #if SCSI_DETACH + nin_detach(&dp->isahd); + #endif /* SCSI_DETACH */ + } + + /* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int + card_intr(struct pccard_devinfo *dp) + { + /* call interrupt proc*/ + ninintr(dp->isahd.id_unit); + return(1); + } + #endif /* NCARD > 0 */ + + + + int + nin_probe(struct isa_device *dev) + { + u_char ChipId; + int nin_unit = dev->id_unit; + + /* unit_num is too much*/ + if(nin_unit > NNIN) { + return 0; + } + + nin_data[nin_unit].BaseAddress = dev->id_iobase; + + + ChipId = inb(nin_data[nin_unit].BaseAddress+FIFOSTATUS); + Ns3DebugPrint(0x10,("nin_probe:BaseAddress[%x],irq[%x],ChipId[%x]\n",nin_data[nin_unit].BaseAddress,dev->id_irq,ChipId)); + if (ChipId < 0x11 || 0x1f < ChipId) { + return 0; + } + + Ns3FindAdapter(nin_unit); + if( !Ns3Initialize(nin_unit) ) { + return 0; + } + + return 8; + } + + int + nin_attach(struct isa_device *dev) + { + int masunit; + static u_long versprobe=0; /* max 32 controllers */ + int unit = dev->id_unit; + struct scsibus_data *scbus; + + nin_data[unit].sc_link.adapter_unit = unit; + nin_data[unit].sc_link.adapter_targ = 7; /* adapter's scsi id*/ + nin_data[unit].sc_link.adapter = &nin_switch; + nin_data[unit].sc_link.device = &nin_dev; + + nin_data[unit].sc_link.adapter_softc = &(nin_data[unit]); + /* nin[unit].sc_link.flags = SDEV_BOUNCE; */ + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if(!scbus) + return 0; + + /*scbus->maxtarg = 7;*/ + scbus->maxlun = 3; + scbus->adapter_link = &nin_data[unit].sc_link; + + + scsi_attachdevs(scbus); + + return 1; + } + + #ifdef SCSI_DETACH + static void + nin_detach(struct isa_device *dev) + { + int unit = dev->id_unit; + struct scsibus_data *scbus; + + scbus = (struct scsibus_data *)scsi_extend_get((&nin_data[unit])->sc_link.scsibus); + scsi_detachdev(scbus); + } + #endif /* SCSI_DETACH */ + + /* ----------------------------------------------------------- */ + + void nin_minphys(struct buf *bp) + { + #define DEFAULT_FIFOMAX 0x10000 + + if(bp->b_bcount > DEFAULT_FIFOMAX) { + bp->b_bcount = DEFAULT_FIFOMAX; + } + } + + /* + * Return some information to the caller about + * the adapter and its capabilities. + */ + u_int32_t + nin_adapter_info(int unit) + { + /* max number of request per device */ + return 1; + } + /* return (2); * 2 outstanding requests at a time per device */ + + + /* + // Ns3FindAdapter + */ + u_long Ns3FindAdapter(int unit) + { + int baseAddress; /* PSCSI_REGISTER baseAddress; */ + u_long status; + u_char * ioSpace,memSpace; + u_char switches; + u_long mmioBase; + u_long UseRegisterBuffer = 0; + TRANSFER_MODE xferMode; + u_long FifoMax = 0x10000; + u_char dataByte; + #ifdef ULTRA + u_char OptSyncPeriod + #endif + + pnin_softc DevExt = &(nin_data[unit]); + Ns3DebugPrint(0x20, ( "FindAdapter Entered...\n")); + + *((u_char *)&xferMode) = 0; + xferMode.MemMap8 = 1; + xferMode.MemMap16_32 = 1; + xferMode.AdrData24 = 1; + xferMode.IO16_32 = 1; + xferMode.IO8 = 1; + + baseAddress = DevExt->BaseAddress; /* Get I/O addr*/ + + FifoMax = 0x10000; + + + /* Determine IRQ*/ + /* Note: In future release of NT (after .404 March Beta), this value*/ + /* can be returned as 0 and NT will assume we are polling and won't*/ + /* reserve an IRQ for us. Until then, we need to give him something.*/ + + /* See Note Above*/ + + DevExt->SSEntry = 0; + + xferMode.MemMap16_32 = 0; + xferMode.AdrData24 = 0; + xferMode.MemMap8 = 0; + DevExt->TransferMode= *(u_char *)&xferMode; + + /* Set default-trans-mode*/ + (*(u_char *)&xferMode) = 0; + xferMode.FifoTest_Braind = 0; + xferMode.TransferGo = 0; + xferMode.IO16_32 = 1; + /* TransferModeSet & TEST MODE OFF */ + SCSI_WRITE(baseAddress, TRANSFERMODE, *(u_char *)&xferMode); + + DevExt->pXferRead = pio32_datain; + DevExt->pXferWrite = pio32_dataout; + + return TRUE; + } /* end Ns3FindAdapter()*/ + + + + PSPECIFIC_LU_EXTENSION + ScsiPortGetLogicalUnit(u_int8_t TargetId,u_int8_t Lun) + { + int flags; + flags = splbio(); + + if (!table[TargetId][Lun]) { + table[TargetId][Lun] = + malloc(sizeof(SPECIFIC_LU_EXTENSION), M_DEVBUF, M_NOWAIT); + } + splx(flags); + return table[TargetId][Lun]; + } + + + void ScsiPortFreeLogicalUnit(u_int8_t TargetId,u_int8_t Lun) + { + int flags; + flags = splbio(); + + if((TargetId >= 7)||(Lun >= 8)) { + Ns3DebugPrint(0x10,( "ScsiPortFreeLogicalUnit:ID[%x] Lun[%x]\n", + TargetId,Lun)); + splx(flags); + return; + } + + if (table[TargetId][Lun]) { + /* 1105 + free( table[TargetId][Lun] , M_DEVBUF); + table[TargetId][Lun] = 0; + 1105 */ + } + splx(flags); + } + + u_char Ns3FifoTest( int unit,IN PFIFO_TEST pTestMode) + { + TRANSFER_MODE saveMode; + + saveMode.TransferGo = 1; + saveMode.FifoTest_Braind = 0; + saveMode.MemMap8 = 0; + saveMode.AdrData24 = 0; + saveMode.MemMap16_32 = 0; + saveMode.IO8 = 0; + saveMode.IO16_32 = 1; + return(*((u_char *)(&saveMode))); + + } + + + void Ns3ResetScsiBus( pnin_softc DevExt ) + { + + PSPECIFIC_TARGET_EXTENSION targetState; + u_long i; + unsigned long flags; + + u_char dataByte; + int baseAddress = DevExt->BaseAddress; + + if (DevExt->DmaPending == TRUE) { + DevExt->DmaPending = FALSE; + } + DevExt->InterruptPending = FALSE; + + Ns3DebugPrint(0x10, ( "Ns3ResetScsiBus ")); + + SCSI_IRQ_CONTROL(baseAddress, 0xff); /* IRQ all Mssk & clear*/ + + /*****************/ + /* RESET SCSI bus.*/ + /******************/ + + dataByte = 0; + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiRst = 1; + SCSI_WRITE(baseAddress, SCSIBUSCTRL, dataByte); /* SCSI RST On !*/ + + DELAY(RESET_HOLD_TIME); + + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiRst = 0; + SCSI_WRITE(baseAddress, SCSIBUSCTRL, dataByte); /* SCSI RST Off !*/ + /* + dummy read for SCSI RST IRQ/Phase Change + */ + for ( i= 0; i < 5; i++) { + SCSI_READ(baseAddress,IRQPHASESENCE); + } + + /* Set unsyncronus 5MB*/ + for (i = 0; i < 7; i++) { + targetState = &DevExt->TargetState[i]; /* Get pointer*/ + targetState->TargetFlags &= ~PD_SYNCHRONOUS_NEGOTIATION_DONE; + targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; + targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; + } + SCSI_IRQ_CONTROL(baseAddress, 0xff); /* IRQ mask & clear*/ + DevExt->IrqMaskData = 0xff; + + DELAY(RESET_RECOVER_TIME); + } + + + + + + + + + int ninja3_precommand( + PSPECIFIC_LU_EXTENSION *luExt, + pnin_softc devExt, + struct scsi_xfer * Srb) + { + + /* + ** Determine the logical unit that this request is for. + */ + + (*luExt) = ScsiPortGetLogicalUnit( + /* devExt->PathId, */ + Srb->sc_link->target, + Srb->sc_link->lun); + if( !(*luExt) ) { + Srb->error = XS_DRIVER_STUFFUP; + return FALSE; /*TRY_AGAIN_LATER;*/ + } + + /* + ** Setup the context for this target/lun. + */ + + (*luExt)->ActiveLuRequest = Srb; + (*luExt)->SavedDataPointer = Srb->data; + (*luExt)->SavedDataLength = Srb->datalen; + + (*luExt)->PhaseWaitCounter = 0; + devExt->ScsiState = SC_SELECT; + + return TRUE; + } /*ninja3_precommand end*/ + + + void nin_timeout (void *arg); + void nin_timeout (void *arg) + { + pnin_softc DevExt= (pnin_softc) arg; + + struct scsi_xfer *Srb = DevExt->ActiveLogicalUnit->ActiveLuRequest; + int x = splbio (); + + if (! (Srb->flags & SCSI_NOMASK)) + printf ("nin%d/%d/%d (%s%d) timed out\n", + Srb->sc_link->adapter_unit, + Srb->sc_link->target, + Srb->sc_link->lun, + Srb->sc_link->device->name, + Srb->sc_link->dev_unit); + + Ns3ResetScsiBus (DevExt); + Srb->error = XS_TIMEOUT; + Srb->retries = 0; + nin_done(DevExt,XS_TIMEOUT); + + splx (x); + } + int nin_scsi_cmd(struct scsi_xfer * Srb) + { + int x = 0; + int flags = Srb->flags; + static PSPECIFIC_LU_EXTENSION luExtension; + struct scsi_link *sc_link = Srb->sc_link; + pnin_softc deviceExtension = (pnin_softc)sc_link->adapter_softc; + + Ns3DebugPrint (0x10,("nin %d/%d command 0x%x ",Srb->sc_link->target, + Srb->sc_link->lun, Srb->cmd->opcode)); + + if (flags & SCSI_RESET) { + Ns3DebugPrint(0x10, ( "nin_scsi_cmd: Reset Bus.\n")); + + /* Reset Ns3 and SCSI bus.*/ + Ns3ResetScsiBus( deviceExtension ); + return COMPLETE; + } + + if( !ninja3_precommand(&luExtension,deviceExtension,Srb) ) { + return TRY_AGAIN_LATER; + } + if(!Srb) { + Ns3DebugPrint(0x008, ("ninja3_precommand srb = null!!!! \n\n\n")); + return FALSE; + } + if (! (flags & SCSI_NOMASK)) + x = splbio (); + + /* + Initiate a SCSI request. + */ + Ns3StartExecution(deviceExtension, luExtension, Srb); + + if ( Ns3Select(deviceExtension,Srb) ) + Ns3IrqPolling ( deviceExtension->unit ); + + // Usually return SUCCESSFULLY QUEUED. + if (! (flags & SCSI_NOMASK)) { + splx (x); /* 1107 */ + if (Srb->flags & ITSDONE) { + Ns3DebugPrint (0x10,("nin_scsi_cmd SUCCESSFULLY_QUEUED\n")); + return (SUCCESSFULLY_QUEUED); + } + Ns3DebugPrint (0x10,("call timeout\n")); + timeout (nin_timeout, (caddr_t)deviceExtension, (Srb->timeout * hz) / 1000); + Ns3DebugPrint (0x10,("nin%d/%d/%d command queued\n", + Srb->sc_link->adapter_unit, + Srb->sc_link->target, Srb->sc_link->lun)); + Ns3DebugPrint (0x10,("nin_scsi_cmd SUCCESSFULLY_QUEUED\n")); + return (SUCCESSFULLY_QUEUED); + } + + return (Srb->error ? HAD_ERROR : COMPLETE); + + /* + * return values for scsi_cmd() + #define SUCCESSFULLY_QUEUED 0 + #define TRY_AGAIN_LATER 1 + #define COMPLETE 2 + #define HAD_ERROR 3 // do not use this, use COMPLETE + #define ESCAPE_NOT_SUPPORTED 4 + */ + + } /* end nin_scsi_cmd()*/ + + /* + // Routine Name: + // + // Ns3StartExecution + // + // Routine Description: + // + // This routine will start the execution of a SCSI request. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // LuExtension - The logical unit specific information. + // Srb - The Srb command to execute. + // + // Return Value: + // + // None. + // + //----------------------------------------------------------------------- + */ + void Ns3StartExecution( + IN pnin_softc DevExt, + IN PSPECIFIC_LU_EXTENSION LuExtension, + IN struct scsi_xfer *Srb + ) + { + PSPECIFIC_TARGET_EXTENSION targetState; + + if ((Srb->cmd->bytes[0] >> 5) != Srb->sc_link->lun) + { + Srb->cmd->bytes[0] &= 0x1f; + Srb->cmd->bytes[0] |= (Srb->sc_link->lun << 5); + } + + DevExt->TargetId = Srb->sc_link->target; + + /* + Setup the context for this adapter. + */ + DevExt->ActiveLogicalUnit = LuExtension; + DevExt->CurDataPointer = + DevExt->ActiveLogicalUnit->SavedDataPointer; + DevExt->CurDataLength = + DevExt->ActiveLogicalUnit->SavedDataLength; + + /* Set TargetState Ns3MessageDecode */ + DevExt->TargetId = Srb->sc_link->target; + targetState = &DevExt->TargetState[Srb->sc_link->target]; + + /* + // + // Create the identify command. + // + */ + + /* NOT supported DISCONECT */ + if ( + /* (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) || */ + (DevExt->AdapterOption & OPT_NON_DISCONECT) ) + { + DevExt->MessageBuffer[0] = + MSG_IDENTIFYFLAG | Srb->sc_link->lun; + } else { + DevExt->MessageBuffer[0] = + MSG_IDENTIFYFLAG_WITH_DISCON | Srb->sc_link->lun; + } + DevExt->MessageCount = 1; + + /* + // Make SyncMessage if donot Sync Nego + */ + + if (!(targetState->TargetFlags & PD_SYNCHRONOUS_NEGOTIATION_DONE ) && + !(targetState->TargetFlags & PD_DO_NOT_NEGOTIATE) && + + (Srb->cmd->opcode != INQUIRY) /* INQUIRY:Don't Sync Nego */ + ) + { + /* Sync message exchange [sync]*/ + DevExt->MessageCount = 6; + /* extended message out */ + DevExt->MessageBuffer[1] = MSG_EXTENDED; + + /* length */ + DevExt->MessageBuffer[2] = MSG_EXT_SDTR_LEN; + + /* extended message out command */ + DevExt->MessageBuffer[3] = SCSIMESS_SYNCHRONOUS_DATA_REQ; + + #ifdef ULTRA + DevExt->MessageBuffer[4] = DevExt->SynchronousPeriod; + #else + /* Transfer interval 100n = 10M ByteS */ + DevExt->MessageBuffer[4] = SYNCHRONOUS_PERIOD; + #endif + DevExt->MessageBuffer[5] = SYNCHRONOUS_OFFSET; + targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE | + PD_SYNCHRONOUS_TRANSFER_SENT; + + DevExt->MessageCount = 1; + } + + } /* end Ns3StartExecution()*/ + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3IrqPolling + // + // Routine Description: + // + // Interrupt Polling + // + /// + //-----------------------------------------------------------------------*/ + void Ns3IrqPolling ( int unit ) + { + pnin_softc DevExt = &(nin_data[unit]); + int i; + + i = INT_POLL_SEL; + + while (i > 0 ) { + if ( SCSI_IRQ_MONITOR(DevExt->BaseAddress) & 0xb ) + { + ninintr( unit ); + break; + } + /* loop interval 530CS-133MHz : 4.5us */ + DELAY(5); /* DELAY -> DELAY */ + + i--; + } + + /* Timer IRQ Enable*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->TimerIrqMask = 1; + /* SCSI IRQ Enable*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->ScsiIrqMask = 0; + SCSI_IRQ_CONTROL(DevExt->BaseAddress, DevExt->IrqMaskData); + Ns3DebugPrint (0x10,("-- Ns3IrqPolling ends -- ")); + } + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // ninintr + // + // Routine Description: + // + // This routine handles the interrupts for the Ns3. The intention is to + // quickly determine the cause of the interrupt, clear the interrupt, and + // setup to process the SCSI command that is affected by the + // interrupt. + // + // Arguments: + // + // Context - Device adapter context pointer. + // + // Return Value: + // + // TRUE indicates that the interrupt was from this Ns3 adapter, + // FALSE indicates that this interrupt was NOT from us. + // + //----------------------------------------------------------------------- + // boolean -> void + */ + void ninintr( int unit ) + { + long i; + pnin_softc DevExt = &(nin_data[unit]); + int baseAddress = DevExt->BaseAddress; + + + IRQ_STATUS IntIrqStatus; + IRQ_PHASE_SENSE IntIrqPhase; + + unsigned char dataByte; + char TargetId; + PSPECIFIC_TARGET_EXTENSION targetState; + + + *((unsigned char *) &IntIrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + + dataByte = 0; + ((PIRQ_CONTROLP)&dataByte)->ExtIrqMask = 1; + ((PIRQ_CONTROLP)&dataByte)->FifoIrqMask = 1; + ((PIRQ_CONTROLP)&dataByte)->TimerIrqMask = 1; + ((PIRQ_CONTROLP)&dataByte)->ScsiIrqMask = 1; + + SCSI_IRQ_CONTROL(baseAddress, dataByte); /* // IRQ All mask*/ + + IntEntry: + /* from nin_unload */ + + if(DevExt->gone) { + nin_done(DevExt, XS_DRIVER_STUFFUP); + DevExt->ScsiState = SC_BUSFREE; + DevExt->IntWait = FALSE; + return; // TRUE; + } + + if ( *((unsigned char *) &IntIrqStatus) == 0xff ) { + nin_done(DevExt, FALSE/*SRB_STATUS_NO_DEVICE*/); + DevExt->ScsiState = SC_BUSFREE; + DevExt->IntWait = FALSE; + return; /* TRUE;*/ + } + + DevExt->InterruptPending = FALSE; + + /* + // --- Timer interrupt? --- + */ + if ( IntIrqStatus.TimerIrqStatus ) { + dataByte = 0xf0; + ((PIRQ_CONTROLP)&dataByte)->TimerIrqClear = 1; + /* Timer IRQ Clear*/ + SCSI_IRQ_CONTROL(DevExt->BaseAddress, dataByte); + + if ( DevExt->TimerCount != 0 ) { + /* Next TIMER START*/ + SCSI_WRITE(DevExt->BaseAddress, TIMERCOUNT, + DevExt->TimerCycle); + DevExt->TimerCount--; + } + } + + /* + // ---- SCSI IRQ ? ---- + */ + if ( IntIrqStatus.ScsiIrqStatus ) { + *((unsigned char *)&IntIrqPhase) = SCSI_READ(baseAddress, IRQPHASESENCE); + + /* + //---- ReSelection IRQ ? ---- + */ + if (IntIrqPhase.ReselectIrq) { + TargetId =(unsigned char)(SCSI_READ(baseAddress, RESELECTID) & 0x7f); + i = 0xffffffff; + while ( TargetId > 0 ) { + i++; + TargetId = TargetId >> 1; + } + + DevExt->TargetId = i; + DevExt->TargetLun = + DevExt->ActiveLogicalUnit->ActiveLuRequest->sc_link->lun; + do { + dataByte = SCSI_READ(baseAddress, SCSIBUSMON); + } while ( ((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_SEL ); + /* SEL off ?*/ + + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiBSY = 0; /* BUSY Off !*/ + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); + ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; + /* AckEnb , AutoDirection ON !*/ + ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; + /* ( Not same time in BUSY off)*/ + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); + + /* set Sync-parameter*/ + targetState = + &DevExt->TargetState[DevExt->TargetId]; + dataByte = 0; + ((PSYNC_REG)&dataByte)->SyncPeriod = + targetState->SynchronousPeriod; + ((PSYNC_REG)&dataByte)->SyncOffset = + targetState->SynchronousOffset; + + SCSI_WRITE(baseAddress, SYNCREG,dataByte); + SCSI_WRITE(baseAddress, ACKWIDTH, targetState->AckWidth); + + /* Clear transfer clear*/ + dataByte = 0; + ((PPOINTER_CLEAR)&dataByte)->PointerClear = 1; + ((PPOINTER_CLEAR)&dataByte)->AckCounterClear = 1; + ((PPOINTER_CLEAR)&dataByte)->ReqCounterClear = 1; + ((PPOINTER_CLEAR)&dataByte)->HostCounterClear = 1; + SCSI_WRITE(baseAddress, POINTERCLR, dataByte); + + /* LUN isn't defined, not use LunExtension... + wait for Message IN */ + DevExt->ScsiState = SC_RESELECT; + goto IntEnd; + } + + /* + --- SCSI RESET Irq ?---- + */ + if ( IntIrqPhase.ScsiResetIrq ) { + /* Set unsync 5mb */ + for (i = 0; i < 7; i++) { + targetState = &DevExt->TargetState[i]; + targetState->TargetFlags &= ~PD_SYNCHRONOUS_NEGOTIATION_DONE; + targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; + targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; + } + goto IntEnd; + } + + /* + --- Phase Change Interrupt ? --- + */ + if ( IntIrqPhase.PhaseChgIrq ) { + Ns3RunPhase(DevExt, IntIrqPhase ); + goto IntEnd; + } + } + + /* + ---- FIFO Interrupt ? ---- + */ + if ( IntIrqStatus.FifoIrqStatus ) { + /* Interrupt Clear*/ + *((unsigned char *) &IntIrqPhase) = SCSI_READ(baseAddress, IRQPHASESENCE); + /* Still nokori ga aru H*/ + if ( DevExt->CurDataLength ) { + /* before Phase*/ + if ( DevExt->ScsiPrePhase == BP_DATA_IN) + Ns3DataInPhase(DevExt); + else if (DevExt->ScsiPrePhase == BP_DATA_OUT) + Ns3DataOutPhase(DevExt); + } + /*PhaseChange same time ‚É”­¶ ?*/ + if ( IntIrqPhase.PhaseChgIrq ) { + Ns3RunPhase(DevExt, IntIrqPhase ); + } + goto IntEnd; + } + + IntEnd: + + #ifdef USE_INTENTRY + if ( !DevExt->IntWait ) { + *((unsigned char *) &IntIrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if ( *((unsigned char *)&IntIrqStatus) & 0xf ) { + goto IntEntry;/* INT */ + } + } else { + int polltimes; + polltimes = INT_POLL_IRQ * 10000; + for ( i = 0; i< polltimes; i++) { + *((unsigned char *)&IntIrqStatus) = + SCSI_IRQ_MONITOR(baseAddress); + if ( *((unsigned char *)&IntIrqStatus) & 0x0f ) { + goto IntEntry;/* INT */ + /* l.434 */ + } + } + } + #endif /* USE_INTENTRY */ + + /* + --- Reverse IRQ MASK MODE ---- + */ + SCSI_IRQ_CONTROL(baseAddress, DevExt->IrqMaskData); + DevExt->IntWait = TRUE; + + Ns3DebugPrint(0x10,( "ninintr out -----------\n")); + + return ; /* TRUE;*/ + } /* end ninintr()*/ + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3Select + // + // Routine Description: + // + // Perform selection process on SCSI bus. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // + // Return Value: + // + // TRUE : Select Success + /// + //----------------------------------------------------------------------- + */ + boolean Ns3Select( IN pnin_softc DevExt ,struct scsi_xfer *srb) + { + PSPECIFIC_TARGET_EXTENSION targetState; + + int i; + int baseAddress = DevExt->BaseAddress; + unsigned char cdbLength = srb->cmdlen; + u_char *cdb = &(srb->cmd->opcode); + unsigned char BusyByte, dataByte, AtnByte; + + + AtnByte = 0; + ((PSCSI_BUS_CONTROL)&AtnByte)->ScsiATN = 1; + if ( DevExt->AdapterOption & OPT_NO_ATN ) + ((PSCSI_BUS_CONTROL)&AtnByte)->ScsiATN = 0; + + /* + --- Didable all interrupt + */ + dataByte = 0; + ((PIRQ_CONTROLP)&dataByte)->FifoIrqMask = 1; + ((PIRQ_CONTROLP)&dataByte)->TimerIrqMask = 1; + ((PIRQ_CONTROLP)&dataByte)->ExtIrqMask = 1; + ((PIRQ_CONTROLP)&dataByte)->ScsiIrqMask = 1; + SCSI_IRQ_CONTROL(baseAddress, dataByte); + + DevExt->IrqMaskData = dataByte; + + /* + --- CDB -> COMMAND FIFO --- INITIATOR -> target + */ + dataByte = 0; + ((PCOMMAND_CONTROL)&dataByte)->ClrCommandPointer = 1; + SCSI_WRITE(baseAddress,COMMANDCTRL, dataByte); /* CDB FIFO counter Clear*/ + + /* cdbLength--; cdbLength - 1 */ + while (cdbLength > 0) { + Ns3DebugPrint(0x10,( "[%x]",*cdb)); + SCSI_WRITE(baseAddress, COMMANDDATA, *cdb++); + cdbLength--; + } + /* + --- Start Arbitration for Get Bus--- + */ + dataByte = 0; + + + ((PSET_ARBIT)&dataByte)->ArbitGo = 1; + SCSI_WRITE(baseAddress, SETARBIT, dataByte); /* Start Arbitration */ + + DELAY(300); /* 1104 delete after */ + + dataByte = 0; + + i=0; + + while (!( ((PARBIT_STATUS)&dataByte)->ArbitWin || + ((PARBIT_STATUS)&dataByte)->ArbitFail ) ) { + dataByte = SCSI_READ(baseAddress, ARBITSTATUS); /* Get bus? */ + DELAY(1); + i++; + if(100000 < i){ + Ns3DebugPrint(0x10,( "(;_;)[%x] -X-",dataByte)); + ((PARBIT_STATUS)&dataByte)->ArbitFail = 1; + break; + } + } + + if ( ((PARBIT_STATUS)&dataByte)->ArbitFail ) { /* ...I'm looser */ + Ns3DebugPrint(0x10,( " Faild [%x](;_;) -- ",dataByte)); + + dataByte = 0; + ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; + SCSI_WRITE(baseAddress, SETARBIT, dataByte);/* Arbitration flg Clear*/ + + DevExt->ScsiState = SC_BUSFREE; + /* 1112 nin_done(DevExt, XS_SELTIMEOUT); */ + nin_done(DevExt, XS_TIMEOUT); + + /* Timer IRQ Enable*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->TimerIrqMask = 0; + /* SCSI IRQ Enable*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->ScsiIrqMask = 0; + SCSI_IRQ_CONTROL(baseAddress, DevExt->IrqMaskData); + + return(FALSE); + } + + /* Win !*/ + DELAY(2); + + /*----- selection phase -----*/ + dataByte = (1 << SCSI_INITIATOR_ID) | (1 << (srb->sc_link->target)); + /* set initiator ID + target ID */ + SCSI_WRITE(baseAddress, SCSIDATALATCH, dataByte); + + dataByte = 0; + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiSel = 1; + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiBSY = 1; + dataByte |= AtnByte; + SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); /* put SEL + Busy + ATN*/ + + DELAY(3); /*DELEY ScsiPortStallExecution(1); wait 1.2us*/ + + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiDataOutEnb = 1; + SCSI_WRITE(baseAddress,SCSIBUSCTRL , dataByte); /* enable ID out */ + + dataByte = 0; + ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; + SCSI_WRITE(baseAddress, SETARBIT, dataByte); /* Arbitration flag Clear*/ + + DELAY(2); + + dataByte = 0; + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiSel = 1; + dataByte |= AtnByte; + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiDataOutEnb = 1; + SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); /* Busy off*/ + + DevExt->TimerCount = 250; + DevExt->TimerCycle = 1000/51; + SCSI_WRITE(baseAddress, TIMERCOUNT, 1000/51); /* 1msec TIMER START*/ + + do { + BusyByte = SCSI_READ(baseAddress, SCSIBUSMON); + if ( ((PSCSI_BUS_MONITOR)&BusyByte)->Scsi_BSY ) { /*? (busy)*/ + break; + } + + dataByte = SCSI_IRQ_MONITOR(baseAddress); + if ( ((PIRQ_STATUS)&dataByte)->TimerIrqStatus ) { + SCSI_IRQ_CONTROL(baseAddress, dataByte); + DevExt->TimerCount--; + SCSI_WRITE(baseAddress, TIMERCOUNT, 1000/51);/* 1msec TIMER START*/ + } + } while ( DevExt->TimerCount != 0 ); + + dataByte = SCSI_IRQ_MONITOR(baseAddress) & 0xf0; + ((PIRQ_CONTROLP)&dataByte)->TimerIrqClear = 1; /* Clear Timer IRQ*/ + SCSI_IRQ_CONTROL(baseAddress, dataByte); + DevExt->TimerCount = 0; + + if ( ! (((PSCSI_BUS_MONITOR)&BusyByte)->Scsi_BSY) ) { + /* + ----- None... ----- + */ + SCSI_WRITE(baseAddress, SCSIBUSCTRL, 0); /* SEL Off*/ + + DevExt->ScsiState = SC_BUSFREE; + + nin_done(DevExt, XS_SELTIMEOUT/*SRB_STATUS_NO_DEVICE*/); + + /* Timer IRQ Enable*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->TimerIrqMask = 0; + /* SCSI IRQ Enable*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->ScsiIrqMask = 0; + SCSI_IRQ_CONTROL(baseAddress, DevExt->IrqMaskData); + + + Ns3DebugPrint (0x10,("-- Ns3Select FALSE ends -- ")); + return(FALSE); + } + /* + //--- Success Selection --- + */ + dataByte = 0; + dataByte |= AtnByte; + SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); /* SEL off*/ + + DevExt->TimerCount = 0; + SCSI_WRITE(baseAddress, TIMERCOUNT, 0); /* Timer stop */ + SCSI_WRITE(baseAddress, TIMERCOUNT, 0); /* Timer stop needs 2times */ + + /*AutoDirec / ACK Enable (Not same time in SEL off ...) */ + ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; + ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; + SCSI_WRITE(baseAddress,SCSIBUSCTRL, dataByte); + + targetState = &DevExt->TargetState[srb->sc_link->target]; + + /* set sync parameter*/ + dataByte = 0; + ((PSYNC_REG)&dataByte)->SyncPeriod = targetState->SynchronousPeriod; + ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; + SCSI_WRITE(baseAddress, SYNCREG,dataByte); + + SCSI_WRITE(baseAddress, ACKWIDTH, targetState->AckWidth); + + Ns3SetTransferMode( DevExt ); + + DevExt->ScsiState = SC_SELECT; + + /* + Adapter ready for next request. + */ + Ns3DebugPrint(0x01,( "Ns3Select: Select ATN OK. ID = %x ", + DevExt->TargetId)); + DELAY(50); + + DevExt->IntWait = TRUE; + + Ns3DebugPrint (0x10,("-- Ns3Select ends -- ")); + return(TRUE); + + } /* end Ns3Select()*/ + + + + + + boolean Ns3Initialize(int unit) + { + pnin_softc DevExt = &(nin_data[unit]); + + u_long i; u_long FifoMax = 0x10000; + u_char dataByte; + TRANSFER_MODE xferMode; + int baseAddress = DevExt->BaseAddress; + u_char DefaultXfer = 0; + DevExt->unit = unit; + DevExt->BaseAddress = baseAddress; + + #ifndef USE_DISCONECT + DevExt->AdapterOption = OPT_NON_DISCONECT; + #endif /* USE_DISCONECT */ + + *((u_char *)&xferMode) = 0; + + xferMode.MemMap8 = 0; + xferMode.MemMap16_32 = 0; + xferMode.AdrData24 = 0; + xferMode.IO16_32 = 0; + xferMode.IO8 = 1; + + + FifoMax = 0x10000; + + DevExt->SSEntry = 0; + + xferMode.MemMap16_32 = 0; + xferMode.AdrData24 = 0; + xferMode.MemMap8 = 0; + DevExt->TransferMode= *(u_char *)&xferMode; + + /* Set default-trans-mode*/ + (*(u_char *)&xferMode) = 0; + xferMode.FifoTest_Braind = 0; + xferMode.TransferGo = 0; + + + /* TransferModeSet & TEST MODE OFF */ + SCSI_WRITE(baseAddress, TRANSFERMODE, *(u_char *)&xferMode); + + #ifdef USE_32BITTRANSFER + DevExt->pXferRead = pio32_datain; + DevExt->pXferWrite = pio32_dataout; + #else + DevExt->pXferRead = pio8_datain; + DevExt->pXferWrite = pio8_dataout; + #endif /* USE_32BITTRANSFER */ + + /* if hang-up any Phase and resetAthen Busfree Interrupt*/ + SCSI_WRITE(baseAddress, SCSIIRQMODE, 0); /* SCSI IRQ ALL DISABLE*/ + SCSI_IRQ_CONTROL(baseAddress, 0xff); /* IRQ all Mssk & clear */ + #ifdef ULTRA + SCSI_WRITE(baseAddress, CLOCKDIV , 2); /* 40MHz */ + #else + SCSI_WRITE(baseAddress, CLOCKDIV , 1); /* 20MHz */ + #endif + dataByte = 0; + ((PSCSI_IRQ_MODE)&dataByte)->ScsiResetIrqEi = 1; + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; /* Disable FIFO IRQ*/ + ((PSCSI_IRQ_MODE)&dataByte)->ReselectIrqEi = 1; + ((PSCSI_IRQ_MODE)&dataByte)->ScsiPhaseChangeEi = 1; + SCSI_WRITE(baseAddress, SCSIIRQMODE, dataByte); + + SCSI_WRITE(baseAddress, PARITYCTRL , 0); /* Parity Disable*/ + SCSI_WRITE(baseAddress, POINTERCLR , 0xf); /* All Pointer Clear*/ + + dataByte = 0; + ((PIF_SELECT)&dataByte)->RegSelect = 1; + SCSI_IF_SELECT(baseAddress, dataByte); /* FIFO Status Read set*/ + + /********************************************************/ + /* Reset Ns3 and SCSI bus.*/ + /********************************************************/ + DevExt->InterruptPending = FALSE; + DevExt->DmaPending = FALSE; + + /*Terminator Off !*/ + SCSI_WRITE(baseAddress, TERMPWRCTRL, 0); /* Terminator Off !*/ + dataByte = SCSI_READ(baseAddress, OTHERCONTROL); + if ( ! ((POTHER_CONTROL)&dataByte)->TermPwrSence ) /* Term Power ?;*/ + SCSI_WRITE(baseAddress, TERMPWRCTRL, 1); /* Terminator ON !*/ + + /********************************************************/ + /*--- SCSI BUS RESET ---*/ + /********************************************************/ + Ns3ResetScsiBus( DevExt ); + + /********************************************************/ + /*--- Cable Check ---*/ + /********************************************************/ + DevExt->ScsiCable = TRUE; + if ( (SCSI_READ(baseAddress,SCSIDATAIN)) || + (SCSI_READ(baseAddress,SCSIBUSMON)) ) { + DevExt->ScsiCable = FALSE; + SCSI_WRITE(baseAddress, TERMPWRCTRL, 0); /* Terminator Off !*/ + } + + *(u_char *)&xferMode = DevExt->TransferMode; + + /********************************************************/ + /* Can TransferMode Clear*/ + /********************************************************/ + for ( i = 0; i < 6; i++ ) { + DevExt->CanTransMode[i] = DefaultOk[i]; + } + /********************************************************/ + /* At first, Test for TransferMode in default */ + /********************************************************/ + DefaultXfer = Ns3FifoTest( unit,&DevExt->CanTransMode[0]); + + xferMode =(*(PTRANSFER_MODE)&DefaultXfer); + + + DevExt->TransferMode= *(u_char *)&xferMode; + /* TransferModeSet & TEST MODE OFF */ + SCSI_WRITE(baseAddress, TRANSFERMODE, *(u_char *)&xferMode); + + + if ( xferMode.IO16_32 ) { + DevExt->pXferRead = pio32_datain; + DevExt->pXferWrite = pio32_dataout; + } else if ( xferMode.IO8 ) { + DevExt->pXferRead = pio8_datain; + DevExt->pXferWrite = pio8_dataout; + } + SCSI_WRITE(baseAddress, CLOCKDIV , 2); + + return TRUE; + } /* end Ns3Initialize()*/ + + /* + //----------------------------------------------------------------------- + // Routine Name: + // nin_done + // + // Routine Description: + // + // This routine will perform any clean up operations for the Srb + // and notify the ScsiPort driver of completion. + // + //----------------------------------------------------------------------- + */ + void nin_done( IN pnin_softc DevExt, + IN int err_code ) + { + struct scsi_xfer *srb = DevExt->ActiveLogicalUnit->ActiveLuRequest; + + ScsiPortFreeLogicalUnit( + srb->sc_link->target, + srb->sc_link->lun); + + untimeout (nin_timeout, (caddr_t) DevExt); + srb->error = err_code; + srb->flags |= ITSDONE; + scsi_done(srb); + + } /* end nin_done()*/ + + + + + + /* + //---------------------------------------------------------------------------- + // Set transger mode & ruotine + //---------------------------------------------------------------------------- + */ + void Ns3SetTransferMode( IN pnin_softc DevExt ) + { + PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; + unsigned char dataByte; + + LuExtension->pXferRead = DevExt->pXferRead; + LuExtension->pXferWrite = DevExt->pXferWrite; + + /* FIFOTest & Option Set TransferMode*/ + dataByte = DevExt->TransferMode; + + ((PTRANSFER_MODE)&dataByte)->TransferGo = 1; + ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 1; + /* Set transfer mode*/ + SCSI_WRITE(DevExt->BaseAddress, TRANSFERMODE, dataByte); + + } + + + /* + //----------------------------------------------------------------------- + // read FIFO + // + //----------------------------------------------------------------------- + */ + unsigned long read_ack_count ( IN pnin_softc DevExt ) + { + int baseAddress = DevExt->BaseAddress; + unsigned char dataByte; + unsigned char CountL,CountM, CountH; + unsigned long Count, Counter; + + dataByte = 0; + ((PPOINTER_CLEAR)&dataByte)->PointerClear = 1; + SCSI_WRITE(baseAddress, POINTERCLR, dataByte); /* ACK counter read set*/ + + CountL = inb(baseAddress+DATAREG); + CountM = inb(baseAddress+DATAREG); + CountH = inb(baseAddress+DATAREG); + + Counter = (unsigned long)( CountH*65536 + CountM*256 + CountL); + + /* Check Card */ + if ( Counter == 0xffffff ) return (0); + + /* Counter value at Disconnect */ + Count = Counter + DevExt->ActiveLogicalUnit->AckCounter; + Count -= DevExt->ActiveLogicalUnit->TransferedLength; + + return ( Count ); + } + + + /* + //----------------------------------------------------------------------- + // TransferRoutine + // + //----------------------------------------------------------------------- + // + */ + /* + --- PIO 32bit DataInTransfer ---- + */ + void pio32_datain (IN u_int BaseAddress , + char *Buffer, + size_t Length ) + { + if ( Length & 0x3 ) { + Ns3DebugPrint(0x01,( "SCSI_READ_FIFOW [%x] (%x)byte", Buffer , Length)); + SCSI_READ_FIFOW(BaseAddress, Buffer , Length); + } else { + SCSI_READ_FIFOD(BaseAddress, Buffer , Length); + } + } + + /* + --- PIO 32bit DataOutTransfer pXferWrite() ---- + */ + void pio32_dataout (IN u_int BaseAddress , + char *Buffer, + size_t Length ) + { + if ( Length & 0x3 ) { + SCSI_WRITE_FIFOW(BaseAddress, Buffer , Length); + } else { + SCSI_WRITE_FIFOD(BaseAddress, Buffer , Length); + } + } + + /* + --- PIO 8bit DataInTransfer ---- + */ + void pio8_datain (IN u_int BaseAddress , + char *Buffer, + size_t Length ) + { + SCSI_READ_FIFO(BaseAddress, Buffer , Length); + } + + /* + --- PIO 8bit DataOutTransfer ---- + */ + void pio8_dataout (IN u_int BaseAddress , + char *Buffer, + size_t Length ) + { + SCSI_WRITE_FIFO(BaseAddress, Buffer , Length); + } + + + void Ns3BurstRead( IN pnin_softc DevExt ) + { + int flags; + u_long Length; + IRQ_STATUS IrqStatus; + FIFO_STATUS FifoStatus; + uint baseAddress = DevExt->BaseAddress; + PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; + + while( DevExt->CurDataLength > 0 ) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if ( IrqStatus.ScsiIrqStatus ) { + break; + /** PhaseChange ? ***/ + } + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + if ( FifoStatus.FifoFullEmpty ) { + Length = DevExt->CurDataLength; + /* change maxmum transfer size*/ + if ( Length > READ_XFER_CNT) Length = READ_XFER_CNT; + + /* Call for TransferRoutine */ + + (*LuExtension->pXferRead)( baseAddress, + DevExt->CurDataPointer, Length ); + + flags = splbio(); + DevExt->CurDataPointer += Length; + DevExt->CurDataLength -= Length; + DevExt->ActiveLogicalUnit->TransferedLength += Length; + splx(flags); + } + } + + /* See now,but PhaseChange */ + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + + /* Stop PhaseChange interrupt */ + if ( IrqStatus.ScsiIrqStatus ) { /* PhaseChange ?*/ + if ( DevExt->CurDataLength > 0) { + Length = read_ack_count(DevExt); + if (!(Length & 0x80000000)) { /* +[v0.32]*/ + (*LuExtension->pXferRead)( baseAddress, + DevExt->CurDataPointer, Length ); + } + flags = splbio(); + DevExt->CurDataPointer += Length; + DevExt->CurDataLength -= Length; + DevExt->ActiveLogicalUnit->TransferedLength += Length; + splx(flags); + } + } + + DevExt->ScsiState = SC_DATA; + } + /* + //----------------------------------------------------------------------- + // blind write + // + //----------------------------------------------------------------------- + */ + void Ns3BurstWrite( IN pnin_softc DevExt ) + { + u_long Length; + IRQ_STATUS IrqStatus; + FIFO_STATUS FifoStatus; + int baseAddress = DevExt->BaseAddress; + PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; + int flags; + + while( DevExt->CurDataLength > 0 ) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if ( IrqStatus.ScsiIrqStatus ) break; /* PhaseChange ?*/ + + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + if ( FifoStatus.FifoFullEmpty) { + + Length = DevExt->CurDataLength; + /* change maximum transfer number*/ + if ( Length > WRITE_BURST_CNT) Length = WRITE_BURST_CNT; + + /* Call for TransferRoutine */ + (*LuExtension->pXferWrite)( baseAddress, + DevExt->CurDataPointer, Length ); + + flags = splbio(); + DevExt->CurDataPointer += Length; + DevExt->CurDataLength -= Length; + DevExt->ActiveLogicalUnit->TransferedLength += Length ; + splx(flags); + } + } + + /* See now,but PhaseChange after sending */ + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + + /* remain data inFIFO at PhaseChange */ + if ( IrqStatus.ScsiIrqStatus ) { /* PhaseChange ?*/ + if ( (Length = read_ack_count(DevExt)) ) { /* Length is Minus*/ + flags = splbio(); + DevExt->CurDataPointer += Length; + DevExt->CurDataLength -= Length; /* pointerwomodosu*/ + DevExt->ActiveLogicalUnit->TransferedLength += Length ; + splx(flags); + } + } + + DevExt->ScsiState = SC_DATA; + } + /* + //----------------------------------------------------------------------- + // spot read + // + //----------------------------------------------------------------------- + */ + void Ns3SpotRead ( IN pnin_softc DevExt ) + { + u_char dataByte; + int baseAddress = DevExt->BaseAddress; + IRQ_STATUS IrqStatus; + FIFO_STATUS FifoStatus; + u_long FifoCount; + long LoopCount = 0; + u_char ScsiPhase; + long i; + int flags; + PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; + ScsiPhase = SCSI_READ(baseAddress, SCSIBUSMON) & 0x7; + + if ( ScsiPhase == BP_DATA_IN ) { + if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { + dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; /* FIFO IRQ Enable*/ + SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); + /* Release FIFO IRQ MASK */ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; + } + + while (LoopCount == 0) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if ( IrqStatus.ScsiIrqStatus ) break; /* PhaseChange ?*/ + + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + if ( FifoStatus.FifoFullEmpty ) { + dataByte = 0xf0; + ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; + SCSI_IRQ_CONTROL(baseAddress, dataByte); /* IRQ Clear*/ + + /* Read FIFO */ + FifoCount = read_ack_count( DevExt ) & 0xfffffe; + + /* Call for TransferRoutine */ + (*LuExtension->pXferRead)( baseAddress, + DevExt->CurDataPointer, FifoCount ); + + flags = splbio(); + DevExt->CurDataLength -= FifoCount ; + DevExt->CurDataPointer += FifoCount; + DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; + LoopCount++; + + DevExt->IntWait = FALSE; + splx(flags); + + for ( i = 0; i< INT_POLL_IRQ ; i++) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if ( IrqStatus.ScsiIrqStatus ) break; /* PhaseChange ?*/ + + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + if ( FifoStatus.FifoFullEmpty ) { /* FIFO FULL */ + LoopCount = 0; /* One moer*/ + break; + } + DELAY(2);/*ScsiPortStallExecution(2);*/ + } + } + } + } else { + /* other phase*/ + FifoCount = read_ack_count( DevExt ); /* Get FIFOremain*/ + (*LuExtension->pXferRead)( baseAddress, + DevExt->CurDataPointer, FifoCount ); + + flags = splbio(); + DevExt->CurDataLength -= FifoCount ; + DevExt->CurDataPointer += FifoCount; + DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; + splx(flags); + + dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); + /* Disable FIFO IRQ */ + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; + SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); + /* FIFO IRQ MASK*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 1; + + DevExt->IntWait = TRUE; + return; + } + + /* Stoped in PhaseChange */ + if ( IrqStatus.ScsiIrqStatus && + ( FifoCount = read_ack_count(DevExt))) + { + (*LuExtension->pXferRead)( baseAddress, + DevExt->CurDataPointer, FifoCount ); + flags = splbio(); + DevExt->CurDataPointer += FifoCount; + DevExt->CurDataLength -= FifoCount; + DevExt->ActiveLogicalUnit->TransferedLength += FifoCount; + splx(flags); + + dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); + /* Disable FIFO IRQ */ + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; + SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); + + /* FIFO IRQ MASK*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 1; + DevExt->IntWait = TRUE; + } + + DevExt->ScsiState = SC_DATA; /* Wait for next FifoFull */ + } + /* + //----------------------------------------------------------------------- + // + //----------------------------------------------------------------------- + */ + void Ns3SpotWrite ( IN pnin_softc DevExt ) + { + int flags; + u_char dataByte; + int baseAddress = DevExt->BaseAddress; + IRQ_STATUS IrqStatus; + FIFO_STATUS FifoStatus; + u_long FifoCount; + long LoopCount = 0; + long i; + PSPECIFIC_LU_EXTENSION LuExtension = DevExt->ActiveLogicalUnit; + + if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { + dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); + /* FIFO IRQ Enable*/ + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; + SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); + /* Release FIFO IRQ MASK */ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; + } + + while (LoopCount == 0) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if ( IrqStatus.ScsiIrqStatus ) { + break; /* PhaseChange ?*/ + } + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + if ( FifoStatus.FifoFullEmpty) { + dataByte = 0xf0; + ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; + SCSI_IRQ_CONTROL(baseAddress, dataByte); /* IRQ Clear*/ + + FifoCount = WRITE_SPOT_CNT; + if ( DevExt->CurDataLength < WRITE_SPOT_CNT ){ + FifoCount = DevExt->CurDataLength; + } + + /* Call for TransferRoutine */ + (*LuExtension->pXferWrite)( baseAddress, + DevExt->CurDataPointer, FifoCount ); + + flags = splbio(); + DevExt->CurDataLength -= FifoCount ; + DevExt->CurDataPointer += FifoCount;; + DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; + splx(flags); + if ( DevExt->CurDataLength == 0 ) { + DevExt->IntWait = TRUE; + break; + } + + LoopCount++; + DevExt->IntWait = FALSE; + + for ( i = 0; i< INT_POLL_IRQ ; i++) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if ( IrqStatus.ScsiIrqStatus ) { + break; /* PhaseChange ?*/ + } + + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + if ( FifoStatus.FifoFullEmpty ) { /* if FIFO Empty*/ + LoopCount = 0; /* Once more*/ + break; + } + DELAY(2); /* ScsiPortStallExecution(2); */ + } + } + } + + if ( IrqStatus.ScsiIrqStatus ) { /* PhaseChange ?*/ + DevExt->IntWait = TRUE; + } + DevExt->ScsiState = SC_DATA; /* Next FifoEmpty Wait*/ + } + /* + //----------------------------------------------------------------------- + // Slow Read + // + //----------------------------------------------------------------------- + */ + void Ns3SlowRead ( IN pnin_softc DevExt ) + { + int flags; + char *Buffer = DevExt->CurDataPointer; + u_char dataByte; + int baseAddress = DevExt->BaseAddress; + IRQ_STATUS IrqStatus; + FIFO_STATUS FifoStatus; + u_long FifoCount; + long LoopCount = 0; + u_char ScsiPhase; + + dataByte = 0; + ((PTRANSFER_MODE)&dataByte)->TransferGo = 1; + ((PTRANSFER_MODE)&dataByte)->IO8 = 1; + ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 0; + SCSI_WRITE(baseAddress, TRANSFERMODE, dataByte); /* Set Transfer Mode*/ + + ScsiPhase = SCSI_READ(baseAddress, SCSIBUSMON) & 0x7; + + if ( ScsiPhase == BP_DATA_IN ) { + if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { + dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); + /* FIFO IRQ Enable*/ + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; + SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); + /* Release FIFO IRQ MASK*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; + } + while (LoopCount == 0) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + if ( FifoStatus.FifoFullEmpty ) { /* FIFO FULL?*/ + dataByte = 0xf0; + ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; + SCSI_IRQ_CONTROL(baseAddress, dataByte); /* Clear IRQ*/ + } + if ( FifoStatus.FifoFullEmpty || IrqStatus.ScsiIrqStatus) { + FifoCount = read_ack_count( DevExt );/* Get FIFO remain*/ + SCSI_READ_FIFO( baseAddress, Buffer, FifoCount ); + flags = splbio(); + Buffer += FifoCount; + + DevExt->CurDataLength -= FifoCount ; + DevExt->CurDataPointer = Buffer; + DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; + LoopCount++; + splx(flags); + } + } + } else { + /* otheer Phase*/ + FifoCount = read_ack_count( DevExt ); /* read FIFO remain*/ + SCSI_READ_FIFO( baseAddress, Buffer, FifoCount ); + flags = splbio(); + Buffer += FifoCount; + + DevExt->CurDataLength -= FifoCount ; + DevExt->CurDataPointer = Buffer; + DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; + splx(flags); + return; + } + + DevExt->ScsiState = SC_DATA; /* Wait for next FifoFull */ + } + /* + //----------------------------------------------------------------------- + // + //----------------------------------------------------------------------- + */ + void Ns3SlowWrite ( IN pnin_softc DevExt ) + { + char* Buffer = DevExt->CurDataPointer; + u_char dataByte; + int baseAddress = DevExt->BaseAddress; + FIFO_STATUS FifoStatus; + u_long FifoCount; + int flags; + + dataByte = 0; + ((PTRANSFER_MODE)&dataByte)->TransferGo = 1; + ((PTRANSFER_MODE)&dataByte)->IO8 = 1; + ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 0; + SCSI_WRITE(baseAddress, TRANSFERMODE, dataByte); /* TransferModeSet*/ + + if ( ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask) { + dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); + /* FIFO IRQ Enable*/ + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 1; + SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); + /* Enable FIFO IRQ MAS K*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 0; + } + + *((u_char *) &FifoStatus) = SCSI_FIFO_STATUS(baseAddress); + + if ( FifoStatus.FifoFullEmpty) { + dataByte = 0xf0; + ((PIRQ_CONTROLP)&dataByte)->FifoIrqClear = 1; + SCSI_IRQ_CONTROL(baseAddress, dataByte); /* IRQ Clear*/ + + FifoCount = 32; + if ( DevExt->CurDataLength < 32 ) + FifoCount = DevExt->CurDataLength; + + SCSI_WRITE_FIFO ( baseAddress, Buffer, FifoCount ); + flags = splbio(); + Buffer += FifoCount; + + DevExt->CurDataLength -= FifoCount ; + DevExt->CurDataPointer = Buffer; + DevExt->ActiveLogicalUnit->TransferedLength += FifoCount ; + splx(flags); + } + + DevExt->ScsiState = SC_DATA; /* Wait for Next FifoEmpty*/ + + } + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3RunPhase + // + // Routine Description: + // + // This routine runs through the bus phases until some type of completion + // indication is received. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // + // Return Value: + // + // None. + // + //----------------------------------------------------------------------- + */ + void Ns3RunPhase( IN pnin_softc DevExt, + IN IRQ_PHASE_SENSE IrqPhase ) + { + int baseAddress = DevExt->BaseAddress; + u_char dataByte; + u_long Count; + PSPECIFIC_TARGET_EXTENSION targetState; + int flags; + + /* slow transfer proc*/ + if ( IrqPhase.PhaseChgIrq && + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask == 0 ) { + + /* still H*/ + if ( (Count = read_ack_count(DevExt)) ) { + if ( DevExt->ScsiPrePhase == BP_DATA_IN) {/* prvious phase*/ + Ns3DataInPhase(DevExt); + }else { + flags = splbio(); + DevExt->CurDataLength -= Count; /* back pointer*/ + DevExt->CurDataPointer += Count; + /* Number of transfer-length */ + DevExt->ActiveLogicalUnit->TransferedLength += Count; + splx(flags); + } + } + dataByte = SCSI_READ(DevExt->BaseAddress, SCSIIRQMODE); + /* FIFO IRQ desable*/ + ((PSCSI_IRQ_MODE)&dataByte)->FifoIrqEi= 0; + SCSI_WRITE(DevExt->BaseAddress, SCSIIRQMODE, dataByte); + /* FIFO IRQ MASK*/ + ((PIRQ_CONTROLP)&DevExt->IrqMaskData)->FifoIrqMask = 1; + } + + /* + //--- BUS FREE ( DISCONNETCT ) ? ---- + */ + /*interrput in BusFree*/ + if ( IrqPhase.LatchBusFree ) + { + /* trans-mode is FIFOtest/option*/ + dataByte = DevExt->TransferMode; + ((PTRANSFER_MODE)&dataByte)->TransferGo = 0; + ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 0; + /* TransferModeSet*/ + SCSI_WRITE(baseAddress, TRANSFERMODE, dataByte); + + /* Save AckCounter*/ + DevExt->ActiveLogicalUnit->AckCounter = + DevExt->ActiveLogicalUnit->TransferedLength; + + if ( DevExt->ScsiState == SC_COMPLETE ) { + nin_done(DevExt, XS_NOERROR/*SRB_STATUS_NO_DEVICE*/); + DevExt->ScsiState = SC_BUSFREE; + DevExt->IntWait = FALSE; + return; + } else if (DevExt->ScsiState == SC_DISCONNECT ) { + DevExt->ScsiState = SC_BUSFREE; + return; + } + + targetState = &DevExt->TargetState[DevExt ->TargetId]; + if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { + targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; + targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; + } + DevExt->ScsiState = SC_BUSFREE; + return; + } + + if(!DevExt->ActiveLogicalUnit->ActiveLuRequest) { + return; + } /* 1016 */ + + (*(u_char *)&IrqPhase) &= 0x7; + DevExt->ScsiPrePhase = (*(u_char *)&IrqPhase); + + switch (DevExt->ScsiPrePhase) { + case BP_COMMAND: + Ns3SendCDB(DevExt); /*Start commans phase*/ + + break; + + case BP_DATA_IN: + Ns3DataInPhase(DevExt); /* Start data phase*/ + break; + + case BP_DATA_OUT: + Ns3DataOutPhase(DevExt); /* Start data phase*/ + break; + + case BP_STATUS: + Ns3Status(DevExt); + break; + + case BP_MESSAGE_IN: + Ns3MessageIn(DevExt); + break; + + case BP_MESSAGE_OUT: + Ns3MessageOut(DevExt); + break; + + default: + DevExt->ScsiState = SC_COMPLETE; + break; + } + + } /* end Ns3RunPhase()*/ + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3DataInPhase + // + // Routine Description: + // + // This routine sets the DmaPending flag in the device extension, + // calls the OS-specific driver to set up the system DMA chip, + // and returns. Control is received again in DmaStarted when the DMA + // setup is complete. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // + // Return Value: + // + // TRUE if DMA started + // FALSE if missed request + // + //----------------------------------------------------------------------- + */ + void Ns3DataInPhase( IN pnin_softc DevExt ) + { + u_char targetId = DevExt->TargetId; + u_char devType; + /* u_long TransferLength = DevExt->CurDataLength;*/ + + DevExt->InterruptPending = FALSE; /* flag clear*/ + + DevExt->DmaPending = TRUE; + devType = DevExt->DeviceType[targetId]; + + + /*1014*/ + if (!DevExt) { + Ns3DebugPrint(0x10, ("Ns3DataInPhase in DevExt NULL\n")); + return; + } + if (!(DevExt->ActiveLogicalUnit) ) { + Ns3DebugPrint(0x10, ("Ns3DataInPhase in DevExt->ActiveLogicalUnit NULL\n")); + return; + } + if (!(DevExt->ActiveLogicalUnit->ActiveLuRequest) ) { + Ns3DebugPrint(0x10, ("Ns3DataInPhase in DevExt->ActiveLogicalUnit->ActiveLuRequest NULL\n")); + return; + } + + if (( DevExt->ActiveLogicalUnit-> + ActiveLuRequest->datalen < 0x100 + ) || + ( DevExt->ActiveLogicalUnit-> + ActiveLuRequest->datalen & 0x33 + ) ) + { + Ns3SlowRead ( DevExt ); /* Not divaid less than 256, */ + return; + } + + switch ( devType ) { + case 0: + case 5: + Ns3BurstRead( DevExt ); + break; + + default: + Ns3SpotRead ( DevExt ); + break; + } + + } /* end Ns3DataInPhase()*/ + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3DataOutPhase + // + // Routine Description: + // + // This routine sets the DmaPending flag in the device extension, + // calls the OS-specific driver to set up the system DMA chip, + // and returns. Control is received again in DmaStarted when the DMA + // setup is complete. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // + // Return Value: + // + // TRUE if DMA started + // FALSE if missed request + // + //----------------------------------------------------------------------- + */ + void Ns3DataOutPhase( IN pnin_softc DevExt ) + { + u_char targetId = DevExt->TargetId; + u_char devType; + u_char dataByte; + + if(!DevExt) { + Ns3DebugPrint(0x10,( "Ns3DataOutPhase DevExt=NULL!\n")); + return; + } + if(!DevExt->ActiveLogicalUnit) { + Ns3DebugPrint(0x10,( "Ns3DataOutPhase ActiveLogicalUnit=NULL!\n")); + return; + } + if(!DevExt->ActiveLogicalUnit->ActiveLuRequest) { + Ns3DebugPrint(0x10,( "Ns3DataOutPhase ActiveLuRequest=NULL!\n")); + return; + } + + DevExt->InterruptPending = FALSE; /* flag clear*/ + DevExt->DmaPending = TRUE; + devType = DevExt->DeviceType[targetId]; + + + if ( (DevExt->ActiveLogicalUnit-> + ActiveLuRequest->datalen < 0x100) || + (DevExt->ActiveLogicalUnit-> + ActiveLuRequest->datalen & 3) + ) + { + Ns3SlowWrite ( DevExt ); /* Smaller than 256 or x/4 != 0 ? */ + return; + } + + dataByte = DevExt->TransferMode; + /* Set TransferMode in FIFOTest / Option */ + /* munya.. */ + + Ns3SpotWrite ( DevExt ); + } /* end Ns3DataOutPhase()*/ + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3SendCDB + // + // Routine Description: + // + // Send the SCSI Command Descriptor Block (CDB) to the indicated target/lun. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // + // Return Value: + // + // None + // + //----------------------------------------------------------------------- + */ + + void Ns3SendCDB( IN pnin_softc DevExt ) + { + int baseAddress = DevExt->BaseAddress; + u_char dataByte; + + dataByte = SCSI_READ(baseAddress, SCSIBUSMON); + if ( ((PSCSI_BUS_MONITOR)&dataByte)->Scsi_ATN ) { /* Still ATN ?*/ + /* SCSI-1 Device */ + dataByte = 0; + ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; + ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; + SCSI_WRITE(baseAddress, SCSIBUSCTRL, dataByte); /* ATN off*/ + } + + /* Clear transfer counter*/ + dataByte = 0; + ((PPOINTER_CLEAR)&dataByte)->PointerClear = 1; + ((PPOINTER_CLEAR)&dataByte)->AckCounterClear = 1; + ((PPOINTER_CLEAR)&dataByte)->ReqCounterClear = 1; + ((PPOINTER_CLEAR)&dataByte)->HostCounterClear = 1; + SCSI_WRITE(baseAddress, POINTERCLR, dataByte); + + DevExt->ActiveLogicalUnit->AckCounter = 0; + DevExt->ActiveLogicalUnit->HostCounter = 0; + + /* send CDB*/ + dataByte = 0; + ((PCOMMAND_CONTROL)&dataByte)->AutoCommandGo = 1; + ((PCOMMAND_CONTROL)&dataByte)->ClrCommandPointer = 1; + SCSI_WRITE(baseAddress, COMMANDCTRL, dataByte); + + DevExt->ScsiState = SC_UNDETERMINED; + + /* + // Set up the running data pointer info for a possible data transfer. + */ + DevExt->CurDataPointer = + DevExt->ActiveLogicalUnit->SavedDataPointer; + DevExt->CurDataLength = + DevExt->ActiveLogicalUnit->SavedDataLength; + + DevExt->ActiveLogicalUnit->TransferedLength = 0; + + /* Enable Interrupt */ + DevExt->InterruptPending = TRUE; + + } /* end Ns3SendCDB()*/ + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3MessageOut + // + // Routine Description: + // + // This routine will sent the message to the target. + // + //----------------------------------------------------------------------- + */ + void Ns3MessageOut( IN pnin_softc DevExt ) + { + int baseAddress = DevExt->BaseAddress; + u_char dataByte; + u_char * msg = &DevExt->MessageBuffer[0]; + IRQ_STATUS IrqStatus; + + /* MessageOut,NoOperation*/ + if ( DevExt->MessageCount == 0 ) { + DevExt->MessageBuffer[0] = MSG_NOOP; /* MSG_NOOP 0x08 */ + DevExt->MessageCount = 1; + } + + do { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + if (IrqStatus.ScsiIrqStatus) { + break; + } + + dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; + if ( dataByte == BM_MESSAGE_OUT ) { + + if ( DevExt->MessageCount == 1) { /* last byte ?*/ + dataByte = 0; + ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; + ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; + /* ATN Off !*/ + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); + } + + /* message output*/ + SCSI_WRITE(baseAddress ,SCSIDATAWITHACK, *msg); + Ns3WaitForAckOff(DevExt); + + msg++; + DevExt->MessageCount--; + } + } while ( DevExt->MessageCount != 0 ); + + /* phase change. Off ATN */ + if ( IrqStatus.ScsiIrqStatus && DevExt->MessageCount != 0) { + dataByte = 0; + ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; + ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ATN Off !*/ + } + + DevExt->ScsiState = SC_UNDETERMINED; + } /* end Ns3MessageOut()*/ + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3MessageIn + // + // Routine Description: + // + // This routine will receive the message from the target. + // + //----------------------------------------------------------------------- + */ + void Ns3MessageIn( IN pnin_softc DevExt ) + { + PSPECIFIC_LU_EXTENSION luExtension; + struct scsi_xfer * srb; + int baseAddress = DevExt->BaseAddress; + u_char * msg = &DevExt->MessageBuffer[0]; + u_char dataByte; + IRQ_STATUS IrqStatus; + u_long MessageCount = 0; + boolean NegAck = TRUE; + PSPECIFIC_TARGET_EXTENSION targetState; + + DevExt->MessageCount = 0; + + luExtension = DevExt->ActiveLogicalUnit; + if ( luExtension ) { /* reselection = NULL*/ + srb = luExtension->ActiveLuRequest; + targetState = &DevExt->TargetState[srb ->sc_link->target]; + } else { + return; + } + + /* + // --- message first byte + // + read Ninja */ + dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; + /* message in phase? is &req?*/ + if ( dataByte == BM_MESSAGE_IN ) { + /* read msg byte*/ + *msg = SCSI_READ(baseAddress, SCSIDATAIN); + /* srb->SCp.Message = *msg;*/ + + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK On !*/ + + /* if return value is FALSE? */ + Ns3WaitForReqOff(DevExt); /* REQ off ?*/ + + /* + //--- Identify Message ? ---- + */ + if ( *msg & MSG_IDENTIFYFLAG ) {/* 0x80 = MSG_IDENTIFYFLAG ? */ + DevExt->TargetLun = *msg & 0xf; + /* now reselecting?*/ + if ( DevExt->ScsiState == SC_RESELECT ) { + Ns3ProcessReselection(DevExt); + } + } else { + DevExt->ScsiState = SC_UNDETERMINED; + switch ( *msg ) { + case MSG_CMDCOMPLETE : + DevExt->ScsiState = SC_COMPLETE; + break; + + case MSG_DISCONNECT : + /* srb->device->disconnect = 1;*/ + DevExt->ScsiState = SC_DISCONNECT; + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK off !*/ + return; + break; + + case MSG_SAVEDATAPOINTER : + MessageCount = 1; /* Wait DISCONNECT msg*/ + DevExt->ScsiState = SC_DISCONNECT; + luExtension->SavedDataPointer = + DevExt->CurDataPointer; + luExtension->SavedDataLength = + DevExt->CurDataLength; + break; + + case MSG_RESTOREPOINTERS: + DevExt->CurDataPointer = luExtension->SavedDataPointer; + DevExt->CurDataLength = luExtension->SavedDataLength; + break; + + case MSG_EXTENDED : + MessageCount = 6; /* max-len ext-msg*/ + if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) + MessageCount = 4; + NegAck = FALSE; /* Not NEG ACK at last byte*/ + break; + + case MSG_MESSAGE_REJECT: + Ns3DebugPrint(0x008, ("MSG_MESSAGE_REJECT\n")); + if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { + targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; + targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; + } + break; + + } + } + + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK Off !*/ + + msg++; + DevExt->MessageCount ++; + } + + /********************************************************/ + /* --- get next-message*/ + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + while ( !(IrqStatus.ScsiIrqStatus)) { /* still phase-chg*/ + + dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; + + /* no next-msg & control-line not message-in*/ + /*-[v0.50] for OLY MO*/ + /* if ((MessageCount == 0) && ((dataByte & 0x7) != BP_MESSAGE_IN) )*/ + /* break;*/ + + /* Is mgs-in phase & req ?*/ + if ( dataByte == BM_MESSAGE_IN ) { + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + /*if PhaseChange here,maybe Reselection Message*/ + if ( IrqStatus.ScsiIrqStatus ) break; + + *msg = SCSI_READ(baseAddress, SCSIDATAIN);/* read msg-byte */ + + if ( *msg == MSG_DISCONNECT ) { + Ns3DebugPrint(0x008, ("MsgIn:msg == MSG_DISCONNECT\n")); + /* srb->device->disconnect = 1;*/ + DevExt->ScsiState = SC_DISCONNECT; + } + + + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); /* ACK On !*/ + + /* if return value is FALSE? */ + Ns3WaitForReqOff(DevExt); /* REQ Off ?*/ + if ( ( MessageCount != 1) || ( MessageCount == 1 && NegAck )) { + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte);/* ACK Off !*/ + } + + msg++; + DevExt->MessageCount ++; + if ( MessageCount != 0 ) MessageCount--; + + /* if Neg ACK at last Byte Mod, finish*/ + if ( MessageCount == 0 && !NegAck ) break; + } + *((u_char *) &IrqStatus) = SCSI_IRQ_MONITOR(baseAddress); + } /* while ( !(IrqStatus.ScsiIrqStatus)); wait for PhaseChange */ + + if (DevExt->MessageBuffer[0] == MSG_EXT_SDTR ) { + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; /* ACK Off !*/ + if (Ns3MessageDecode( DevExt )) /* Is Message after Decode*/ + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiATN = 1; /* ATN On !*/ + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); + } + + } /* end Ns3MessageIn()*/ + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3Status + // + // Routine Description: + // + // This routine will obtain the status from the target. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // + // Return Value: + // + // None + // + //----------------------------------------------------------------------- + */ + void Ns3Status( IN pnin_softc DevExt ) + { + u_char status; + /* u_char srbStatus;*/ + u_char dataByte; + struct scsi_xfer *srb ; + /*= DevExt->ActiveLogicalUnit->ActiveLuRequest;*/ + int baseAddress = DevExt->BaseAddress; + + if(!DevExt->ActiveLogicalUnit) { + /* panic("Ns3Status:DevExt->ActiveLogicalUnit == NULL[1]");*/ + Ns3DebugPrint(0x008, ("Ns3Status:DevExt->ActiveLogicalUnit == NULL \n")); + return; + } + + srb = DevExt->ActiveLogicalUnit->ActiveLuRequest; + + if(!srb) { + Ns3DebugPrint(0x008, ("Ns3Status srb = null!! \n")); + return; + } + + dataByte = SCSI_READ(baseAddress, SCSIBUSMON) & S_PHASE_MASK; + if ( dataByte == BM_STATUS ) { /* Is Status Phase &req ?*/ + + status = SCSI_READ(baseAddress, SCSIDATAWITHACK);/* read Status byte*/ + + /* srb->SCp.Status = status;*/ + switch (status) { + case SCSI_CONDITION_MET: + /* srb->flags |= WAS_SENSE;*/ + case SCSI_OK: + case SCSI_INTERM: + case SCSI_INTERMEDIATE_COND_MET: + if ( (srb->cmd) && /* this line added at 1014 */ + (srb->cmd->opcode == 0x12) && + (srb->sc_link->lun == 0) ){ /* !! */ + DevExt->DeviceType[srb->sc_link->target] = + *(u_char *)(srb->data); + if ( DevExt->DeviceType[srb->sc_link->target] == 6 || /*+[v1.02]*/ + DevExt->DeviceType[srb->sc_link->target] == 3) { + PSPECIFIC_TARGET_EXTENSION targetState; + targetState = &DevExt-> + TargetState[srb->sc_link->target]; + targetState->TargetFlags |= + PD_SYNCHRONOUS_NEGOTIATION_DONE; + } + } + srb->datalen = /*datalen = srb->DataTransferLength = */ + DevExt->ActiveLogicalUnit->TransferedLength ; + /* srbStatus = SRB_STATUS_SUCCESS;*/ + break; + + case SCSI_CHECK: + case SCSI_COMMAND_TERMINATED: + /* srbStatus = SRB_STATUS_ERROR;*/ + break; + + case SCSI_BUSY: + case SCSI_RESERVATION_CONFLICT: + case SCSI_QUEUE_FULL: + default: + /* srbStatus = SRB_STATUS_BUSY;*/ + break; + } + + Ns3WaitForAckOff(DevExt); + + /********************************************************/ + /* If some error condition already occurred (e.g., parity error), we'll*/ + /* let that one take priority.*/ + /********************************************************/ + /* + if (srb->SrbStatus == SRB_STATUS_PENDING) + srb->SrbStatus = srbStatus; + */ + } /* if BM_STATUS*/ + + DevExt->ScsiState = SC_UNDETERMINED; + + } /* end Ns3Status()*/ + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // Ns3WaitForAckOff + // + // Routine Description: + // Spin checking the status of the Ns3 adapter until it indicates that + // the SCSI ACK line is Low + // + // Return Value: + // TRUE - indicates that the SCSI REQUEST line was Negated in time. + // FALSE - indicates timeout occurred while waiting for the SCSI REQUEST + // line. + //----------------------------------------------------------------------- + */ + boolean Ns3WaitForAckOff( pnin_softc DevExt ) + { + int baseAddress = DevExt->BaseAddress; + u_long spinCount = REQUEST_SPIN_WAIT; + u_char dataByte; + + do { + dataByte = SCSI_READ(baseAddress, SCSIBUSMON); + if ( !((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_ACK ) {/* ACK Off ?*/ + return TRUE; + } + DELAY(2); + } while (spinCount--); + + nin_done(DevExt, XS_TIMEOUT); + return FALSE; + + } /* end Ns3WaitForAckOff()*/ + + + /* + //----------------------------------------------------------------------- + // Routine Name: + // + // Ns3WaitForReqOff + // + // Routine Description: + // + // Spin checking the status of the Ns3 adapter until it indicates that + // the SCSI REQUEST line is high. + // + // Arguments: + // + // DevExt - Device adapter context pointer. + // + // Return Value: + // + // TRUE - indicates that the SCSI REQUEST line was asserted in time. + // FALSE - indicates timeout occurred while waiting for the SCSI REQUEST + // line. + //----------------------------------------------------------------------- + */ + boolean Ns3WaitForReqOff( pnin_softc DevExt ) + { + int baseAddress = DevExt->BaseAddress; + u_long spinCount = REQUEST_SPIN_WAIT; + u_char dataByte; + + do { + dataByte = SCSI_READ(baseAddress, SCSIBUSMON); + if ( !((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_REQ ) /* REQ Off ?*/ + return TRUE; + } while (spinCount--); + + /* must call scsi_done()? */ + + Ns3DebugPrint(0x04, ("TIMEOUT\n")); + nin_done(DevExt, XS_TIMEOUT); + return FALSE; + + } /* end Ns3WaitForReqOff()*/ + + + + + /* + //----------------------------------------------------------------------------- + // RESELECTION + //----------------------------------------------------------------------------- + */ + boolean Ns3ProcessReselection( IN pnin_softc DevExt ) + { + /* u_char pathId = 0;*/ + PSPECIFIC_LU_EXTENSION luExtension; + struct scsi_xfer *srb; + PSPECIFIC_TARGET_EXTENSION targetState; + int baseAddress = DevExt->BaseAddress; + u_char dataByte; + + targetState = &DevExt->TargetState[DevExt->TargetId]; + + /********************************************************/ + /* Get the specific logical unit extension.*/ + /********************************************************/ + luExtension = ScsiPortGetLogicalUnit(/*DevExt,pathId,*/ + DevExt->TargetId, /* DevExt->sc_link.target,//argetId,*/ + DevExt->TargetLun); /* sc_link.lun ->TargetLun );*/ + + DevExt->ActiveLogicalUnit = luExtension; + + if (!luExtension || !luExtension->ActiveLuRequest) { + /* SP_INVALID_RESELECTION ErrorCode,*/ + Ns3DebugPrint(0x10,( "Reselection Failed.\n")); + + /* + // Send an abort message. Put the message-in the buffer, set the + // state, indicate that a disconnect is expected after this, and + // set the attention signal. + */ + + DevExt->MessageBuffer[0] = MSG_ABORT; + DevExt->MessageCount = 1; + + /* + // + // The target and logical unit specified are not valid. A + // MESSAGE REJECT message has been set up. Set ATN and accept the + // message. + // + */ + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + /* ATN ON !-> send-mdg mode*/ + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiATN = 1; + /* ACK Off !*/ + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); + nin_done(DevExt,XS_BUSY); + return(FALSE); + + } + + Ns3DebugPrint(0x10,( "Ns3ProResel: Resel Start ID=%d\n", + DevExt->TargetId)); + + srb = luExtension->ActiveLuRequest; + + Ns3SetTransferMode( DevExt ); /* TransferModeSet*/ + /* + // + // A reselection has been completed. Set the active logical unit, + // restore the active data pointer, set the state. + // In addition, any adapter flags set by a pending select must be + // cleared using the disconnect mask. + // + */ + DevExt->CurDataPointer = luExtension->SavedDataPointer; + DevExt->CurDataLength = luExtension->SavedDataLength; + DevExt->MessageCount = 0; + + dataByte = SCSI_READ(baseAddress, SCSIBUSCTRL); + ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; /* ACK Off !*/ + SCSI_WRITE(baseAddress , SCSIBUSCTRL, dataByte); + + return(TRUE); + } + + + boolean Ns3MessageDecode( IN pnin_softc DevExt ) + { + struct scsi_xfer *srb = + DevExt->ActiveLogicalUnit->ActiveLuRequest; + PSPECIFIC_TARGET_EXTENSION targetState = + &DevExt->TargetState[srb ->sc_link->target]; + PSCSI_EXMSG exMsg; + long offset; + long i; + int flags; + + exMsg = (PSCSI_EXMSG)DevExt->MessageBuffer; + + switch (exMsg->MessageType) { + case SCSIMESS_MODIFY_DATA_POINTER: + /********************************************************/ + /* Verify the message length.*/ + /********************************************************/ + if (exMsg->MessageLength != SCSIMESS_MODIFY_DATA_LENGTH) { + /********************************************************/ + /* Reject the message.*/ + /********************************************************/ + DevExt->MessageCount = 1; + DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; + return(TRUE); + } + + /********************************************************/ + /* Calculate the modification to be added to the data pointer.*/ + /********************************************************/ + offset = 0; + for (i = 0; i < 4; i++) { + /* ???? offset << 8;*/ + offset += exMsg->ExArg.MODIFY.modifier[i]; + } + + /********************************************************/ + /* Verify that the new data pointer is still within the range*/ + /* of the buffer.*/ + /********************************************************/ + + if (DevExt->CurDataLength - offset > + /* srb->DataTransferLength ||*/ + srb->datalen ||/*srb->datalen ||*/ + ((long) DevExt->CurDataLength - offset) < 0 ) + { + /********************************************************/ + /* The new pointer is not valid, so reject the message.*/ + /********************************************************/ + DevExt->MessageCount = 1; + DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; + return(TRUE); + } + /********************************************************/ + /* Everything has checked out, so update the pointer.*/ + /********************************************************/ + flags = splbio(); + DevExt->CurDataPointer += offset; + DevExt->CurDataLength -= offset; + splx(flags); + + /********************************************************/ + /* Everything is ok, so accept the message as is.*/ + /********************************************************/ + DevExt->MessageCount = 0; + DevExt->ScsiState = SC_COMPLETE_OK; /*MessageAccepted;*/ + return(FALSE); + + case SCSIMESS_SYNCHRONOUS_DATA_REQ: + /********************************************************/ + /* A SYNCHRONOUS DATA TRANSFER REQUEST message was received.*/ + /* Make sure the length is correct.*/ + /********************************************************/ + + if ( exMsg->MessageLength != SCSIMESS_SYNCH_DATA_LENGTH) { + /********************************************************/ + /* The length is invalid reject the message.*/ + /********************************************************/ + DevExt->MessageCount = 1; + DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; + return(TRUE); + } + + /********************************************************/ + /* If synchrouns negotiation has been disabled for this request,*/ + /* then reject any synchronous messages; however, when synchronous*/ + /* transfers are allowed then a new attempt can be made.*/ + /********************************************************/ + + if (srb != NULL && + !(targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) + /* && srb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER*/ + ) { + /********************************************************/ + /* Reject the synchronous transfer message since synchonrous*/ + /* transfers are not desired at this time.*/ + /********************************************************/ + DevExt->MessageCount = 1; + DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; + return(TRUE); + } + /********************************************************/ + /* Call WdDecodeSynchronousMessage to decode the message and*/ + /* formulate a response if necessary.*/ + /* NcrDecodeSynchronousRequest will return FALSE if the*/ + /* message is not accepable and should be rejected.*/ + /********************************************************/ + if (!Ns3DecodeSynchronousRequest( + DevExt, + targetState, + srb->sc_link->target, + (boolean)!(targetState->TargetFlags & + PD_SYNCHRONOUS_TRANSFER_SENT) )) + { + /********************************************************/ + /* Indicate that a negotiation has been done in the logical*/ + /* unit and clear the negotiation flags.*/ + /********************************************************/ + targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; + targetState->TargetFlags &=~(PD_SYNCHRONOUS_TRANSFER_SENT); + + /********************************************************/ + /* The message was not acceptable so send a MESSAGE_REJECT.*/ + /********************************************************/ + DevExt->MessageCount = 1; + DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; + return(TRUE); + } + + /********************************************************/ + /* If a reponse was expected, then set the state for a message-out.*/ + /* Otherwise, NcrDecodeSynchronousRequest has put a reponse*/ + /* in the message buffer to be returned to the target.*/ + /********************************************************/ + + if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT){ + /********************************************************/ + /* We initiated the negotiation, so no response is necessary.*/ + /********************************************************/ + targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; + targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; + return(FALSE); + } + + /********************************************************/ + /* Set up the state to send the reponse. The message count is*/ + /* still correct.*/ + /********************************************************/ + DevExt->ScsiState = SC_MSG_OUT;/* MessageOut;*/ + targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; + return(TRUE); + + case SCSIMESS_WIDE_DATA_REQUEST: + /********************************************************/ + /* A WIDE DATA TRANSFER REQUEST message was received.*/ + /********************************************************/ + DevExt->MessageCount = 1; + DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; + return(TRUE); + + default: + /********************************************************/ + /* This is an unknown or illegal message, so send message REJECT.*/ + /********************************************************/ + DevExt->MessageCount = 1; + DevExt->MessageBuffer[0] = MSG_MESSAGE_REJECT; + return(TRUE); + } + } + /* + //----------------------------------------------------------------------------- + // SYNCHRONOUS_DATA_REQ + // + //Routine Description: Ns3DecodeSynchronousRequest + // + // This function decodes the synchronous data transfer request message from + // the target. It will update the synchronous message in the buffer and the + // synchronous transfer parameters in the logical unit extension. These + // parameters are specific for the WD 53C9X protocol chip. The updated + // message in the device extension message buffer might be returned to the + // target. + // + // This function should be called before the final byte of the message is + // accepted from the SCSI bus. + // + //Arguments: + // + // DevExt - Supplies a pointer to the adapter-specific device + // extension. + // + // LuExtension - Supplies a pointer to the logical unit's device extension. + // The synchronous transfer fields are updated in this structure to + // reflect the new parameter in the message. + // + // ResponseExpected - When set, indicates that the target initiated the + // negotiation and that it expects a response. + // + //Return Value: + // + // TRUE - Returned if the request is acceptable. + // + // FALSE - Returned if the request should be rejected and a synchronous + // transfer should be used. + // + //----------------------------------------------------------------------------- + */ + boolean Ns3DecodeSynchronousRequest( + IN pnin_softc DevExt, + PSPECIFIC_TARGET_EXTENSION TargetState, + IN u_char TargetID, + IN boolean ResponseExpected ) + { + PSCSI_EXMSG exMsg; + long period; + long i; + u_char dataByte; + + exMsg = (PSCSI_EXMSG) DevExt->MessageBuffer; + + /********************************************************/ + /* Determine the transfer offset. It is the minimum of the SCSI protocol*/ + /* chip's maximum offset and the requested offset.*/ + /********************************************************/ + if (exMsg->ExArg.SYNCS.ReqAckOffset > SYNCHRONOUS_OFFSET) { + + if (!ResponseExpected) { + /********************************************************/ + /* The negotiation failed for some reason, fall back to*/ + /* asynchronous data transfer.*/ + /********************************************************/ + TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; + TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; + TargetState->AckWidth = 0; + return(FALSE); + } + + exMsg->ExArg.SYNCS.ReqAckOffset = SYNCHRONOUS_OFFSET; + TargetState->SynchronousOffset = SYNCHRONOUS_OFFSET; + + } else { + TargetState->SynchronousOffset = exMsg->ExArg.SYNCS.ReqAckOffset; + } + + /********************************************************/ + /* If the offset requests asynchronous transfers then set the default*/ + /* period and return.*/ + /********************************************************/ + + if (exMsg->ExArg.SYNCS.ReqAckOffset == ASYNCHRONOUS_OFFSET) + { + TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; + TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; + TargetState->AckWidth = 0; + return(TRUE); + } + + /********************************************************/ + /* Check to see if the period is less than the SCSI protocol chip can*/ + /* use. If it is then update the message with our minimum and return.*/ + /********************************************************/ + + if (exMsg->ExArg.SYNCS.TransferPeriod < SYNCHRONOUS_PERIOD ) + { + if (!ResponseExpected) { + /********************************************************/ + /* The negotiation failed for some reason, fall back to*/ + /* asynchronous data transfer.*/ + /********************************************************/ + TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; + TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; + TargetState->AckWidth = 0; + return(FALSE); + } + + exMsg->ExArg.SYNCS.TransferPeriod = SYNCHRONOUS_PERIOD; + } + + period = exMsg->ExArg.SYNCS.TransferPeriod; + + for ( i=0; i= SyncTable[i].StartPeriod) && + (period <= SyncTable[i].EndPeriod) + ) + break; + } + if (i >= SYNC_TABLE_MAX) { + /********************************************************/ + /* The requested transfer period is too long for the SCSI protocol*/ + /* chip. Fall back to synchronous and reject the request.*/ + /********************************************************/ + TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; + TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; + TargetState->AckWidth = 0; + return(FALSE); + } else { + TargetState->SynchronousPeriod = SyncTable[i].TransferPeriod; + TargetState->AckWidth = SyncTable[i].AckWidth; + } + + /********************************************************/ + /* Set the synchronous data transfer parameter registers*/ + /* to the new values. These must be set before a data transfer*/ + /* is started. If a response message is received then the parameters*/ + /* must be reset.*/ + /********************************************************/ + + dataByte = 0; + ((PSYNC_REG)&dataByte)->SyncPeriod = TargetState->SynchronousPeriod; + ((PSYNC_REG)&dataByte)->SyncOffset = TargetState->SynchronousOffset; + + SCSI_WRITE( DevExt->BaseAddress, ACKWIDTH,TargetState->AckWidth); + SCSI_WRITE( DevExt->BaseAddress, SYNCREG ,dataByte); + + return(TRUE); + + } + + Index: PAO/sys/i386/isa/scc.c diff -c /dev/null PAO/sys/i386/isa/scc.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:04 1998 --- PAO/sys/i386/isa/scc.c Sun Dec 6 07:47:42 1998 *************** *** 0 **** --- 1,990 ---- + /* + * IBM Smart Capture Card driver. + * + * Copyright (c) 1996 + * Takeshi OHASHI and Yoshihisa NAKAGAWA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Takeshi OHASHI + * and Yoshihisa NAKAGAWA. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KOJI OKAMURA, TAKESHI OHASHI AND + * CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Changed by Yoshihisa NAKAGAWA + * Changed by Takeshi OHASHI + * Changed by Hidetoshi KIMURA + * Version 0.36, Nov 24, 1996. + * + */ + + #include "scc.h" + + #if NSCC > 0 + + #undef REMAP_MEM_WIN /* define to remap memory window */ + #define PCCARD_MEM /* It is working now */ + + #ifdef REMAP_MEM_WIN + #undef PCCARD_MEM + #endif + #ifdef PCCARD_MEM + #undef REMAP_MEM_WIN + #endif + + #define FREEBSD22 /* define for 2.2-SNAP */ + #undef FREEBSD215R /* define for FreeBSD-2.1.5-R */ + #undef FREEBSD210R /* define for FreeBSD-2.1.0-R */ + + #ifdef FREEBSD22 + #undef FREEBSD215R + #undef FREEBSD210R + #undef BUGGY_UIO + #endif + #ifdef FREEBSD215R + #undef FREEBSD210R + #undef BUGGY_UIO + #endif + #ifdef FREEBSD210R + #define FREEBSD215R + #define BUGGY_UIO + #endif + + #undef SOFT_INTR /* define to use splbio(), undef to use disable_intr() */ + #define SCC_DEBUG 0 /* define to report infomation for debugging */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #ifdef DEVFS + #include + #endif /* DEVFS */ + + #include + #include + + #ifdef PC98 + #include + #else + #include + #endif + #include + + #ifdef ACTUALLY_LKM_NOT_KERNEL + #include + #include + #include + #endif /* ACTUALLY_LKM_NOT_KERNEL */ + + #include + + struct scc_softc { + u_long flags; /* SCC_ACTIVE|SCC_OPEN */ + caddr_t maddr; + int msize; + int iobase; + int unit; + struct proc *p; /* ? */ + u_long signal_num; /* ? */ + u_short irq; + scc_card_t scc; + int slot; /* PC-card slot */ + int gone; /* PC-card removed */ + + #ifdef DEVFS + void *devfs_token_scc; + void *devfs_token_ctl; + #endif + } scc_softc[NSCC]; + + #define SCCMASK 0x7f + #define CTLMASK 0x80 + + #define UNIT(dev) minor(dev)&SCCMASK + #define ISCTL(dev) minor(dev)&CTLMASK + + static int scc_probe(struct isa_device *id); + static int scc_attach(struct isa_device *id); + + struct isa_driver sccdriver = { scc_probe, scc_attach, "scc" }; + + #ifdef FREEBSD215R + + #define STATIC_CDEVSW + + #else /* FREEBSD215R */ + + static d_open_t scc_open; + static d_close_t scc_close; + static d_read_t scc_read; + static d_write_t scc_write; + static d_ioctl_t scc_ioctl; + static d_select_t scc_select; + static d_mmap_t scc_mmap; + + #define STATIC_CDEVSW static + #define CDEV_MAJOR 76 + static struct cdevsw scc_cdevsw = + { scc_open, scc_close, scc_read, scc_write, /* 76 */ + scc_ioctl, nostop, nullreset, nodevtotty, /* SCC */ + scc_select, scc_mmap, NULL, "scc", + NULL, -1 }; + + #endif /* FREEBSD215R */ + + /* PCCARD suport */ + #include "card.h" + #if NCARD > 0 + #include + #include + #include + #include + #endif /* NCARD > 0 */ + + /* PCCARD Support */ + #if NCARD > 0 + /* + * PC-Card (PCMCIA) specific code. + */ + static int scc_card_intr(struct pccard_devinfo *); /* Interrupt handler */ + void sccunload(struct pccard_devinfo *); /* Disable driver */ + static int sccinit(struct pccard_devinfo *); /* init device */ + static int scc_probe_pccard(struct pccard_devinfo *); + void sccintr(int unit); + + #ifdef PCCARD_MEM + static struct pccard_devinfo *dev_tab[NSCC]; + #endif /* PCCARD_MEM */ + + static int scc_already_init = 0; + static int probed[NSCC]; + + static struct pccard_device scc_info = + { + "scc", + sccinit, + sccunload, + scc_card_intr, + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + /* This should also include net_imask?? */ + }; + + DATA_SET(pccarddrv_set, scc_info); + + /* + * Initialize the device - called from Slot manager. + * if first is set, then initially check for + * the device's existence before initialising it. + * Once initialised, the device table may be set up. + */ + int + sccinit(struct pccard_devinfo *devi) + { + struct scc_softc *sc=(struct scc_softc *)&scc_softc[devi->pd_unit]; + static int already_sccinit[NSCC]; + int unit = devi->pd_unit; + /* + * validate unit number. + */ + if (unit >= NSCC) + return(ENODEV); + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + #if SCC_DEBUG > 0 + printf("Start Probe scc\n"); + #endif + + #ifdef ACTUALLY_LKM_NOT_KERNEL + if (!probed[unit]) { + probed[unit] = 1; + } + #endif /* ACTUALLY_LKM_NOT_KERNEL */ + + if (scc_probe_pccard(devi)==0) + return(ENXIO); + #if SCC_DEBUG > 0 + printf("Start attach scc\n"); + #endif + if (scc_attach(&devi->isahd)==0) + return(ENXIO); + /* + * XXX TODO: + * If it was already inited before, the device structure + * should be already initialised. Here we should + * reset (and possibly restart) the hardware, but + * I am not sure of the best way to do this... + */ + already_sccinit[devi->pd_unit] = 1; + printf("scc%d: init\n", devi->pd_unit); + #ifdef PCCARD_MEM + dev_tab[devi->pd_unit] = devi; + #endif /* PCCARD_MEM */ + + sc->slot = devi->slt->slotnum; + + return(0); + } + /* + * sccunload - unload the driver and clear the table. + * XXX TODO: + * This is called usually when the card is ejected, but + * can be caused by the modunload of a controller driver. + * The idea is reset the driver's view of the device + * and ensure that any driver entry points such as + * read and write do not hang. + */ + void + sccunload(struct pccard_devinfo *devi) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[devi->pd_unit]; + + ss->flags &= ~SCC_ALIVE; + ss->gone = 1; + #if 0 + #ifdef PCCARD_MEM + dev_tab[devi->pd_unit] = NULL; + #endif /* PCCARD_MEM */ + #endif + + #if 0 /* Ohashi */ + #ifdef ACTUALLY_LKM_NOT_KERNEL + --scc_already_init; + #endif /* ACTUALLY_LKM_NOT_KERNEL */ + #endif /* 0 Ohashi */ + } + + /* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int + scc_card_intr(struct pccard_devinfo *devi) + { + sccintr(devi->pd_unit); + return(1); + } + + /* + * scc_probe_pccard - Probe routine for PC-Card + */ + static int + scc_probe_pccard(struct pccard_devinfo *devi) + { + #if 0 + struct scc_softc *ss=(struct scc_softc *)&scc_softc[devp->id_unit]; + #endif + + #if SCC_DEBUG > 0 + printf("scc_probe_pccard\n"); + #endif + + #if 0 + if (inb(ss->iobase) & 0x7f == 0x7f) { + return (0); /* not found */ + } + #endif + return (0x04); /* always found result when this is called */ + } + #endif /* NCARD > 0 */ + + int + scc_probe(struct isa_device *devp) + { + #if NCARD > 0 + #ifndef ACTUALLY_LKM_NOT_KERNEL + ++scc_already_init; + #endif /* !ACTUALLY_LKM_NOT_KERNEL */ + if (!probed[devp->id_unit]) { + probed[devp->id_unit] = 1; + } + #endif /* NCARD > 0 */ + + #if SCC_DEBUG > 0 + printf("scc_card_probe\n"); + #endif + return 0; + } + + int + scc_attach(struct isa_device *devp) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[devp->id_unit]; + int unit = devp->id_unit; + #if NCARD > 0 + static int attached[NSCC]; + #endif /* NCARD > 0 */ + + if (unit >= NSCC) + return (0); + + if (!attached[unit]) { + attached[unit] = 1; + } + + ss->iobase = devp->id_iobase; + ss->irq = devp->id_irq; + ss->maddr = devp->id_maddr; + ss->msize = devp->id_msize; + ss->unit = devp->id_unit; + ss->flags = SCC_ALIVE; + ss->gone = 0; + + #if SCC_DEBUG > 0 + if (ss->maddr == NULL) + printf("scc iobase = %x, irq = %x, maddr = %x, msize = %x\n", + ss->iobase, ss->irq, ss->maddr, ss->msize); + else + printf("scc iobase = %x, irq = %x, maddr = %x, msize = %x\n", + ss->iobase, ss->irq, kvtop(ss->maddr), ss->msize); + #endif + + #ifdef DEVFS + /* devsw, minor, type, uid, gid, perm, fmt, ... */ + ss->devfs_token_scc = + devfs_add_devswf(&scc_cdevsw, unit, DV_CHR, + UID_ROOT, GID_WHEEL, 0644, "scc%n", unit); + ss->devfs_token_ctl = + devfs_add_devswf(&scc_cdevsw, unit | CTLMASK, DV_CHR, + UID_ROOT, GID_WHEEL, 0644, "sccctl%n", unit); + #endif + + #if SCC_DEBUG > 0 + printf("scc_attach\n"); + #endif + + return 1; + } + + + STATIC_CDEVSW int + scc_open(dev_t dev, int flags, int fmt, struct proc *p) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[UNIT(dev)]; + #ifdef PCCARD_MEM + struct slot *slt; + #endif /* PCCARD_MEM */ + #ifdef SOFT_INTR + int s; + #endif /* SOFT_INTR */ + + #if SCC_DEBUG > 0 + printf("scc_open\n"); + #endif + + if (ss == NULL) + return ENXIO; + if (ss->gone) + return ENXIO; + if (ISCTL(dev)) + return 0; + #ifdef PCCARD_MEM + slt = dev_tab[UNIT(dev)]->slt; + if (slt == NULL || slt->state != filled) + return (ENXIO); + #endif /* PCCARD_MEM */ + + if (!(ss->flags & SCC_ALIVE)) + return ENXIO; + + if (ss->flags & SCC_OPEN) + return EBUSY; + + #ifdef SOFT_INTR + s = splbio(); + #else + disable_intr(); + #endif /* SOFT_INTR */ + + ss->flags |= SCC_OPEN; + ss->p = 0; + ss->signal_num = 0; + + ss->scc.geomet.width = SCC_NTSCWIDTH; + ss->scc.geomet.height = SCC_NTSCHEIGHT; + ss->scc.mode = SCC_NTSC; + ss->scc.format = SCC_RGB565; + InitVPX(ss->iobase, ss->scc.mode, 0, ss->scc.geomet.width, + ss->scc.geomet.height, 1, ss->scc.format, UNIT(dev)); + + ss->scc.color.brightness = SCC_DEFBRIGHTNESS; + ss->scc.color.contrast = SCC_DEFCONTRAST; + ss->scc.color.saturation = SCC_DEFSATURATION; + ss->scc.color.hue = SCC_DEFHUE; + SetVPXColor(ss->scc.color.brightness, ss->scc.color.contrast, + ss->scc.color.saturation, ss->scc.color.hue, UNIT(dev)); + + ss->scc.tv.tuntype = TUNETYPE; + ss->scc.tv.channel = 7; + ss->scc.tv.fine = 0; + ss->scc.tv.country = 0; /* Japan:0 USA:1 */ + SetTVChannel(ss->scc.tv.tuntype, ss->scc.tv.channel, + ss->scc.tv.fine, ss->scc.tv.country, UNIT(dev)); + + #ifdef SOFT_INTR + splx(s); + #else + enable_intr(); + #endif /* SOFT_INTR */ + + return 0; + } + + STATIC_CDEVSW int + scc_close(dev_t dev, int flags, int fmt, struct proc *p) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[UNIT(dev)]; + + if (ISCTL(dev)) + return 0; + + if (!(ss->flags & SCC_ALIVE)) + return ENXIO; + + ss->flags &= ~SCC_OPEN; + ss->p = 0; + ss->signal_num = 0; + + #if SCC_DEBUG > 0 + printf("scc_close\n"); + #endif + return 0; + } + + STATIC_CDEVSW int + scc_write(dev_t dev, struct uio *uio, int ioflag) + { + #if SCC_DEBUG > 0 + printf("scc_write\n"); + #endif + return ENXIO; + } + + #if defined(REMAP_MEM_WIN) /* remap memory window */ + /* START from pcic.h pcic.c */ + #define PCIC_INDEX_0 0x3E0 /* index reg, chips 0 and 1 */ + #define PCIC_DATA_0 0x3E1 /* data register, chips 0 and 1 */ + #define PCIC_INDEX_1 0x3E2 /* index reg, chips 1 and 2 */ + #define PCIC_DATA_1 0x3E3 /* data register, chips 1 and 2 */ + + #define INDEX(slot) ((slot) < 4 ? PCIC_INDEX_0 : PCIC_INDEX_1) + #define DATA_(slot) ((slot) < 4 ? PCIC_DATA_0 : PCIC_DATA_1) + #define OFFSET(slot) ((slot) % 4 * 0x40) + + #define MEM_START_ADDR(window) (((window) * 0x08) + 0x10) + #define MEM_STOP_ADDR(window) (((window) * 0x08) + 0x12) + #define MEM_OFFSET(window) (((window) * 0x08) + 0x14) + + #define MEM_ENABLE_BIT(window) ((1) << (window)) + + #define IO_STOP_ADDR(window) ((window) ? PCIC_IO1_SPL : PCIC_IO0_SPL) + #define IO_ENABLE_BIT(window) ((window) ? PCIC_IO1_EN : PCIC_IO0_EN) + #define IO_CS16_BIT(window) ((window) ? PCIC_IO1_CS16 : PCIC_IO0_CS16) + + enum memtype { COMMON, ATTRIBUTE }; + + static inline unsigned char pcic_getb (int slot, int reg); + void pcic_putb (int slot, int reg, unsigned char val); + static inline unsigned short pcic_getw (int slot, int reg); + static inline void pcic_putw (int slot, int reg, unsigned short val); + void pcic_map_memory (int slot, int window, unsigned long sys_addr, + unsigned long card_addr, unsigned long length, + enum memtype type, int width); + void pcic_unmap_memory (int slot, int window); + + static inline unsigned char + pcic_getb (int slot, int reg) + { + outb (INDEX(slot), OFFSET (slot) + reg); + return inb (DATA_(slot)); + } + + void + pcic_putb (int slot, int reg, unsigned char val) + { + outb (INDEX(slot), OFFSET (slot) + reg); + outb (DATA_(slot), val); + } + + static inline unsigned short + pcic_getw (int slot, int reg) + { + return pcic_getb (slot, reg) | (pcic_getb (slot, reg+1) << 8); + } + + static inline void + pcic_putw (int slot, int reg, unsigned short val) + { + pcic_putb (slot, reg, val & 0xff); + pcic_putb (slot, reg + 1, (val >> 8) & 0xff); + } + + void + pcic_map_memory (int slot, int window, unsigned long sys_addr, + unsigned long card_addr, unsigned long length, + enum memtype type, int width) + { + unsigned short offset; + unsigned short mem_start_addr; + unsigned short mem_stop_addr; + + sys_addr >>= 12; + card_addr >>= 12; + length >>= 12; + /* + * compute an offset for the chip such that + * (sys_addr + offset) = card_addr + * but the arithmetic is done modulo 2^14 + */ + offset = (card_addr - sys_addr) & 0x3FFF; + /* + * now OR in the bit for "attribute memory" if necessary + */ + if (type == ATTRIBUTE) { + offset |= (PCIC_REG << 8); + /* REG == "region active" pin on card */ + } + /* + * okay, set up the chip memory mapping registers, and turn + * on the enable bit for this window. + * if we are doing 16-bit wide accesses (width == 2), + * turn on the appropriate bit. + * + * XXX for now, we set all of the wait state bits to zero. + * Not really sure how they should be set. + */ + mem_start_addr = sys_addr & 0xFFF; + if (width == 2) + mem_start_addr |= (PCIC_DATA16 << 8); + mem_stop_addr = (sys_addr + length) & 0xFFF; + + pcic_putw (slot, MEM_START_ADDR(window), mem_start_addr); + pcic_putw (slot, MEM_STOP_ADDR(window), mem_stop_addr); + pcic_putw (slot, MEM_OFFSET(window), offset); + /* + * Assert the bit (PCIC_MEMCS16) that says to decode all of + * the address lines. + */ + pcic_putb (slot, PCIC_ADDRWINE, + pcic_getb (slot, PCIC_ADDRWINE) | + MEM_ENABLE_BIT(window) | PCIC_MEMCS16); + } + + void + pcic_unmap_memory (int slot, int window) + { + /* + * seems like we need to turn off the enable bit first, after which + * we can clear the registers out just to be sure. + */ + pcic_putb (slot, PCIC_ADDRWINE, + pcic_getb (slot, PCIC_ADDRWINE) & ~MEM_ENABLE_BIT(window)); + pcic_putw (slot, MEM_START_ADDR(window), 0); + pcic_putw (slot, MEM_STOP_ADDR(window), 0); + pcic_putw (slot, MEM_OFFSET(window), 0); + } + /* END from pcic.h pcic.c */ + #endif /* defined(REMAP_MEM_WIN) */ + + STATIC_CDEVSW int + scc_read(dev_t dev, struct uio *uio, int ioflag) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[UNIT(dev)]; + long times, page, count, offset, vsync, vsync_offset; + long uio_resid, uio_offset; + int status=0; + int i; + #ifdef PCCARD_MEM + struct slot *slt; + struct mem_desc *mp; + int win = 0; + #endif /* PCCARD_MEM */ + #ifdef SOFT_INTR + int s; + #endif /* SOFT_INTR */ + + if (ss->gone) + return ENODEV; + + if ((ss->flags & SCC_ALIVE)==0) + return ENXIO; + + if (ISCTL(dev)) + return ENXIO; + + if ((ss->flags & SCC_OPEN)==0) + return EBUSY; + + if (ss->scc.spdmode == SCC_SLOW) + FreezeVPX(0, UNIT(dev)); + + #ifdef PCCARD_MEM + slt = dev_tab[UNIT(dev)]->slt; + if (slt == NULL || slt->state != filled) + return(ENXIO); + #if 0 + if (win < 0 || win >= slt->ctrl->maxmem) + return(EINVAL); + #endif + mp = &slt->mem[win]; + #endif /* PCCARD_MEM */ + + uio_resid = uio->uio_resid; + uio_offset = uio->uio_offset; + vsync = ss->scc.geomet.width * 2 * 6; /* ad hoc */ + times = (uio_resid + vsync) / ss->msize; + if (times * ss->msize < uio_resid + vsync) + ++times; + for (i=0; imsize; + offset = vsync_offset % ss->msize; + count = min(uio_resid, ss->msize - offset); + + if (ss->gone) + return ENODEV; + + #ifdef SOFT_INTR + s = splbio(); + #else + disable_intr(); + #endif + + #if defined(REMAP_MEM_WIN) /* remap memory window */ + pcic_unmap_memory(ss->slot, 0); + pcic_map_memory(ss->slot, 0, kvtop(ss->maddr), + page * ss->msize, ss->msize, COMMON, 1); + #if SCC_DEBUG > 1 + printf("scc_read maddr=%x, offset=%x, count=%x\n", + kvtop(ss->maddr), offset, count); + #endif + #endif /* defined(REMAP_MEM_WIN) */ + #ifdef PCCARD_MEM + /* unmap memory */ + mp->flags = 0; + slt->ctrl->mapmem(slt, win); + + /* map memory */ + mp->flags = MDF_ACTIVE; + mp->card = page * ss->msize; + mp->size = ss->msize + 0x1000; + mp->start = (caddr_t)kvtop(ss->maddr); + slt->ctrl->mapmem(slt, win); + #endif /* PCCARD_MEM */ + + status = uiomove(ss->maddr + offset, count, uio); + + #ifdef SOFT_INTR + splx(s); + #else + enable_intr(); + #endif /* SOFT_INTR */ + + uio_resid -= count; + uio_offset += count; + #if SCC_DEBUG > 1 + printf("uio->uio_offset=%lx ", uio->uio_offset); + printf("uio->uio_resid=%lx\n", uio->uio_resid); + printf(" uio_offset=%lx ", uio_offset); + printf(" uio_resid=%lx\n", uio_resid); + #endif /* SCC_DEBUG > 1 */ + #ifdef BUGGY_UIO + uio->uio_resid = uio_resid; + uio->uio_offset = uio_offset; + #endif /* BUGGY_UIO */ + } + + if (ss->scc.spdmode == SCC_SLOW) + FreezeVPX(1, UNIT(dev)); + + if (uio->uio_resid > 0) + return (ENOSPC); + else + return (status); + } + + STATIC_CDEVSW int + scc_ioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[UNIT(dev)]; + scc_geomet_t *geomet; + scc_tv_t *tv; + scc_color_t *color; + int *inttmp; + + if (ss->gone) + return (ENODEV); + if (!data) return(EINVAL); + + if (ISCTL(dev)) + printf("ioctl by sccctl\n"); + + switch(cmd){ + case SCCSETMODE: + inttmp = (int *)data; + if ((*inttmp != SCC_PAL) && (*inttmp != SCC_NTSC)) + return (EINVAL); + ss->scc.mode = *inttmp; + InitVPX(ss->iobase, ss->scc.mode, 0, ss->scc.geomet.width, + ss->scc.geomet.height, 1, ss->scc.format, UNIT(dev)); + break; + case SCCGETMODE: + inttmp = (int *)data; + *inttmp = ss->scc.mode; + break; + case SCCSETGEO: + geomet = (struct scc_geomet *)data; + if (ss->scc.mode == SCC_PAL) { + if (geomet->width <= 0 || + geomet->width > SCC_PALWIDTH || + geomet->height <= 0 || + geomet->height > SCC_PALHEIGHT) + return (EINVAL); + } + else { /* SCC_NTSC */ + if (geomet->width <= 0 || + geomet->width > SCC_NTSCWIDTH || + geomet->height <= 0 || + geomet->height > SCC_NTSCHEIGHT) + return (EINVAL); + } + ss->scc.geomet = *geomet; + SetVPXRect(ss->scc.geomet.width, ss->scc.geomet.height, + UNIT(dev)); + break; + case SCCGETGEO: + geomet = (struct scc_geomet *)data; + *geomet = ss->scc.geomet; + break; + case SCCSETFMT: + inttmp = (int *)data; + if (*inttmp < SCC_YUV422 || *inttmp > SCC_RGB555) + return (EINVAL); + ss->scc.format = *inttmp; + InitVPX(ss->iobase, ss->scc.mode, 0, ss->scc.geomet.width, + ss->scc.geomet.height, 1, ss->scc.format, UNIT(dev)); + break; + case SCCGETFMT: + inttmp = (int *)data; + *inttmp = ss->scc.format; + break; + case SCCSETSPDMODE: + inttmp = (int *)data; + if (*inttmp != SCC_SLOW && *inttmp != SCC_FAST) + return (EINVAL); + ss->scc.spdmode = *inttmp; + break; + case SCCGETSPDMODE: + inttmp = (int *)data; + *inttmp = ss->scc.spdmode; + break; + case SCCSETTVCHANNEL: + tv = (struct scc_tv *)data; + if (tv->country == 0) { /* Japan */ + if (tv->channel < SCC_MINCHANNELJP || + tv->channel > SCC_MAXCHANNELJP) + return (EINVAL); + } + else { /* USA */ + if (tv->channel < SCC_MINCHANNELUS || + tv->channel > SCC_MAXCHANNELUS) + return (EINVAL); + } + ss->scc.tv = *tv; + SetTVChannel(ss->scc.tv.tuntype, ss->scc.tv.channel, + ss->scc.tv.fine, ss->scc.tv.country, UNIT(dev)); + break; + case SCCGETTVCHANNEL: + tv = (struct scc_tv *)data; + *tv = ss->scc.tv; + break; + case SCCSETCOLOR: + color = (struct scc_color *)data; + if (color->brightness < 0 || + color->brightness > SCC_MAXBRIGHTNESS || + color->contrast < 0 || + color->contrast > SCC_MAXCONTRAST || + color->saturation < 0 || + color->saturation > SCC_MAXSATURATION || + color->hue < 0 || + color->hue > SCC_MAXHUE) + return (EINVAL); + + ss->scc.color = *color; + SetVPXColor(ss->scc.color.brightness, ss->scc.color.contrast, + ss->scc.color.saturation, ss->scc.color.hue, + UNIT(dev)); + break; + case SCCGETCOLOR: + color = (struct scc_color *)data; + *color = ss->scc.color; + break; + default: + return ENOTTY; + } + + return 0; + } + + STATIC_CDEVSW int + scc_select(dev_t dev, int rw, struct proc *p) + { + return ENXIO; + } + + /* + * Interrupt procedure. + * Just call a user level interrupt routine. + */ + void + sccintr(int unit) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[unit]; + + if (ss->gone) + return; + + if (ss->p && ss->signal_num) + psignal(ss->p, ss->signal_num); + } + + STATIC_CDEVSW int + scc_mmap(dev_t dev, vm_offset_t offset, int nprot) + { + struct scc_softc *ss=(struct scc_softc *)&scc_softc[UNIT(dev)]; + #ifdef PCCARD_MEM + struct slot *slt; + struct mem_desc *mp; + int win = 0; + #endif /* PCCARD_MEM */ + + if (ss->gone) + return ENODEV; + + if ((ss->flags & SCC_ALIVE)==0) + return ENXIO; + + if (ISCTL(dev)) + return ENXIO; + + if ((ss->flags & SCC_OPEN)==0) + return EBUSY; + + if (offset != 0) { + printf("scc mmap failed, offset = 0x%x != 0x0\n", offset); + return -1; + } + + #if defined(REMAP_MEM_WIN) /* remap memory window */ + pcic_unmap_memory(ss->slot, 0); + pcic_map_memory(ss->slot, 0, kvtop(ss->maddr), + 0, ss->msize, COMMON, 1); + #if SCCDEBUG > 1 + printf("scc_mmap maddr=%x, offset=%x, count=%x\n", + kvtop(ss->maddr), offset, count); + #endif + #endif /* defined(REMAP_MEM_WIN) */ + #ifdef PCCARD_MEM + slt = dev_tab[UNIT(dev)]->slt; + if (slt == NULL || slt->state != filled) + return(ENXIO); + mp = &slt->mem[win]; + + /* unmap memory */ + mp->flags = 0; + slt->ctrl->mapmem(slt, win); + + /* map memory */ + mp->flags = MDF_ACTIVE; + mp->card = 0; + mp->size = ss->msize + 0x1000; + mp->start = (caddr_t)kvtop(ss->maddr); + slt->ctrl->mapmem(slt, win); + #endif /* PCCARD_MEM */ + + if ((nprot & PROT_EXEC) || (nprot & PROT_WRITE)) + return -1; + + return i386_btop(ss->maddr); + } + + #ifndef FREEBSD215R + static void scc_drvinit(void *unused) + { + static scc_devsw_installed = 0; + dev_t dev; + + if (!scc_devsw_installed) { + dev = makedev(CDEV_MAJOR, scc_devsw_installed); + cdevsw_add(&dev, &scc_cdevsw, NULL); + ++scc_devsw_installed; + } + } + + SYSINIT(sccdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,scc_drvinit,NULL) + #endif /* FREEBSD215R */ + + #ifdef ACTUALLY_LKM_NOT_KERNEL + + MOD_DEV(scc, LM_DT_CHAR, CDEV_MAJOR, &scc_cdevsw); + + static int + scc_load(struct lkm_table *lkmtp, int cmd) + { + pccard_add_driver(&scc_info); + scc_drvinit(NULL); + return 0; + } + + static int + scc_unload(struct lkm_table *lkmtp, int cmd) + { + pccard_remove_driver(&scc_info); + return 0; + } + + static int + scc_stat(struct lkm_table *lkmtp, int cmd) + { + return 0; + } + + int + scc_mod(struct lkm_table *lkmtp, int cmd, int var) + { + #define _module scc_module + DISPATCH(lkmtp, cmd, var, scc_load, scc_unload, scc_stat); + } + #endif /* ACTUALLY_LKM_NOT_KERNEL */ + #endif /* NSCC */ + Index: PAO/sys/i386/isa/scc_cs.h diff -c /dev/null PAO/sys/i386/isa/scc_cs.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:04 1998 --- PAO/sys/i386/isa/scc_cs.h Sun Dec 6 07:47:43 1998 *************** *** 0 **** --- 1,275 ---- + /* + * IBM Smart Capture Card driver. + * + * Copyright (c) 1995 + * International Business Machines Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by International + * Business Machines Corporation. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 5. Redistributions are permitted provided for Linux/FreeBSD systems. + * If you want to support other operating system, please contact with + * IBM Smart Capture Card technical support desk. + * 6. Do not ask IBM product services and support about Linux/FreeBSD + * drivers since International Business Machines Corporation does + * not officially support them. + * THIS SOFTWARE IS PROVIDED BY INTERNATIONAL BUSINESS MACHINES + * CORPORATION AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL INTERNATIONAL BUSINESS MACHINES + * CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Changed by Koji OKAMURA + * Changed by Yoshihisa NAKAGAWA + * Changed by Takeshi OHASHI + * Version 0.34, Aug 11, 1996. + * + */ + + #if defined(__linux__) + #define MAXPCMCIA 2 + #define NSCC MAXPCMCIA + #endif /* linux */ + + /* flags in softc */ + #define SCC_OPEN 0x01 /* device open */ + #define SCC_ALIVE 0x02 /* probed and attached */ + + typedef unsigned char BYTE; + typedef unsigned short WORD; + typedef unsigned long DWORD; + + void WriteReg(BYTE, BYTE); + BYTE ReadReg(BYTE); + BYTE FPbusy(void); + void i2cwr8(BYTE, BYTE, BYTE); + BYTE i2crd8(BYTE, BYTE); + void i2cwr16(BYTE, BYTE, WORD); + WORD i2crd16(BYTE, BYTE); + void i2cwdata(BYTE); + BYTE i2crdata(void); + void i2cstart(void); + void i2cstop(void); + BYTE i2crack(void); + BYTE i2cwack(void); + BYTE i2cwnack(void); + void i2cbwr(BYTE, BYTE); + BYTE i2cbrd(BYTE); + BYTE i2cwait(void); + + void SetTVStandard(WORD,int); + BYTE SetTVChannel(BYTE, BYTE, BYTE, BYTE, int); + void FreezeVPX(BYTE,int); + void SetVPXRect(WORD, WORD, int); + void InitVPX(WORD, BYTE, BYTE, WORD, WORD, BYTE, BYTE, int); + void SetVPXColor(BYTE, BYTE, WORD, WORD, int); + void WaitCapture(BYTE,int ); + void SetVPXFmt(BYTE, int); + void SetVideoFilter(WORD, int); + void SetIRQState(BYTE, int); + + + #define DATA 0x03BC /* addresses to support accesses to*/ + #define STATUS 0x03BD /* the Parallel Port 1 - Type 1 */ + #define CONTROL 0x03BE + #define DACMASK 0x03C6 + #define DACSTAT 0x03C7 + #define DACRMDX 0x03C7 + #define DACINDX 0x03C8 + #define DACDATA 0x03C9 + + /* I2C addresses */ + #define VPXI2C 0x43 /* I2C address of VPX version TC5, overraids previous */ + /* #define VPXI2C 0x01 // I2C address of VPX version TC4 */ + #define PETI2C 0x61 /* I2C address of the Philips European Tuner */ + + /* VPX registers */ + #define FPRD 0x0026 + #define FPWR 0x0027 + #define FPDAT 0x0028 + #define FPSTA 0x0029 + + #define VSDT 0x00E7 + #define AGCREF 0x00B2 + #define ACCREF 0x00A0 + #define CLPPK 0x0027 + #define SPL 0x0023 + #define BKS 0x0040 + #define BKR 0x0041 + #define SDT 0x001B + + #define I2C_ID0 0x0000 /* Manufacture ID (0xEC for VPX C4) */ + #define I2C_ID1 0x0001 /* VPX PN (0x80 for VPX C4) */ + #define I2C_ID2 0x0002 /* VPX PN (0x46 for VPX C4) */ + #define DEEM 0x0022 + #define STS 0x0034 + #define LDF 0x0031 + #define YNF 0x0030 + #define AFEND 0x0033 + #define STS 0x0034 + #define REFSIG 0x00D8 /* HREF VREF control for VPX C4 */ + #define CBM_BRI 0x00E6 + #define CBM_CON 0x00E7 + #define FORMAT 0x00E8 + #define FORMAT_C4 0x00E8 /* for C4 */ + #define OFIFO 0x00F0 /* for C4 */ + #define OMUX 0x00F1 + #define OENA 0x00F2 /* Output Enbale for C4 */ + + #define VBEG1 0x0088 + #define VLINEI1 0x0089 + #define VLINEO1 0x008A + #define HBEG1 0x008B + #define HLEN1 0x008C + #define NPIX1 0x008D + + #define VBEG2 0x008E + #define VLINEI2 0x008F + #define VLINEO2 0x0090 + #define HBEG2 0x0091 + #define HLEN2 0x0092 + #define NPIX2 0x0093 + + #define IF1IF2 0x004b + + #define CWDWD 0x009A + #define CWDWD_C4 0x00F0 /* CMD reg for VPX C4 */ + #define TVSTD 0x00f2 /* TV STANDARD for VPX C4 */ + + #define CBM_BRI 0x00E6 + #define CBM_CON 0x00E7 + #define ACCREF 0x00A0 + #define TINT 0x001C + #define FORMAT 0x00E8 + #define OMUX 0x00F1 + #define OENA 0x00F2 + + #define I2CRET 15 + #define FBTBYTES 0x7FFFF + + #define MIX(r,g,b) (((r)*G+(g))*B+(b)) + + #define R 5 /* number of red shades */ + #define G 9 /* number of green shades */ + #define B 5 /* number of blue shades */ + + #define YRG 200 + #define XRG 320 + #define YRV 240 + #define XRV 720 + /* Graphics Modes */ + #define PMONO 0 + #define P332 1 + #define P332D 2 + #define PHICO 3 + + #define REV "1.0" /* program revision code */ + + #define SEL_MAX 8 /* number of selections available */ + /* in the main menu. */ + /* This number MUST match the num. */ + /* of entries in opt_max[] array */ + #define MEMSEG_DFLT 0xD000 + #define GRPSEG_DFLT 0xA000 + #define MEMWTH_DFLT 0x0FFF + /* #define PCICBA_DFLT 0x03E0 */ + #define PCICBA_DFLT 0x03E4 + #define BEBA_DFLT 0x0800 + + #define VCNF0_REG 0x04 /* Video Config. Settings LB Offset */ + #define VCNF1_REG 0x04 /* Video Config. Settings HB Offset */ + #define IOIF_REG 0x05 /* I/O Interface Pins Register Offset */ + + #define SCLW_MSK 0x01 /* mask of the SCLW bit in the IOIF_REG */ + #define SDAW_MSK 0x02 /* mask of the SDAW bit in the IOIF_REG */ + #define SCLR_MSK 0x08 /* mask of the SCLW bit in the IOIF_REG */ + #define SDAR_MSK 0x10 /* mask of the SDAW bit in the IOIF_REG */ + + + #define LOCLK 0 + #define HICLK 1 + #define LODAT 0 + #define HIDAT 1 + + #define I2C_BUSY 0x00010000 + #define I2C_ADR 0 + #define I2C_SUBADR 1 + #define I2C_DAT 2 + + #define I2C_SCL 0 + #define I2C_SDA 1 + + #define NO_COLOR_SETTINGS 8 /* Available color controls */ + #define NO_COLOR_CONTROLS 7 /* Actual number of color controls */ + + /* #define MK_FP(seg,off) ((long)(((WORD)(off)) | (((DWORD)((WORD)(seg))) << 16))) */ + + typedef struct + { + BYTE bpos; /* X position of the field on the screen */ + BYTE row; /* Y position of the field on the screen */ + BYTE size; /* size of the field, max integer */ + BYTE scrn; /* number of the screen */ + WORD indx_port; /* index port address */ + BYTE indx; /* index value */ + WORD data_port; /* data port address */ + } REGFIELD; + + typedef struct + { + char r; + char g; + char b; + } RGB; + + typedef struct CFGSTRUCT + { + WORD wPortAddr; + WORD wVideoAddr; + WORD wCfgFlags; + WORD wVideoSource; + BYTE bColorSettings[NO_COLOR_SETTINGS]; + BYTE aReserved[60]; + } CFGSTRUCT; + + #define MONO_M 1 + #define DITHER_M 2 + + typedef struct VIDEOCFG_S + { + WORD psrc ; + WORD pdst ; + WORD ofst ; + WORD mode ; + WORD direction ; + WORD xd ; + WORD yd ; + WORD h ; + WORD w ; + WORD yStart ; + WORD rs ; + WORD rd ; + } VIDEOCFG_S; + + #define TUNETYPE 0x61 + Index: PAO/sys/i386/isa/scc_subr.c diff -c /dev/null PAO/sys/i386/isa/scc_subr.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:05 1998 --- PAO/sys/i386/isa/scc_subr.c Sun Dec 6 07:47:45 1998 *************** *** 0 **** --- 1,1206 ---- + /* + * IBM Smart Capture Card driver. + * + * Copyright (c) 1995 + * International Business Machines Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by International + * Business Machines Corporation. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 5. Redistributions are permitted provided for Linux/FreeBSD systems. + * If you want to support other operating system, please contact with + * IBM Smart Capture Card technical support desk. + * 6. Do not ask IBM product services and support about Linux/FreeBSD + * drivers since International Business Machines Corporation does + * not officially support them. + * THIS SOFTWARE IS PROVIDED BY INTERNATIONAL BUSINESS MACHINES + * CORPORATION AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL INTERNATIONAL BUSINESS MACHINES + * CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Changed by Koji OKAMURA + * Changed by Yoshihisa NAKAGAWA + * Changed by Takeshi OHASHI + * Version 0.34, Aug 11, 1996. + * + */ + + #if defined(__linux__) + #include + #include "scc_cs.h" + #define outp(P,V) outb((V),(P)) + #define inp(P) inb((P)) + #elif defined(__FreeBSD__) + #include "scc.h" + #include + #include + #define outp(P,V) outb((P),(V)) + #define inp(P) inb((P)) + #endif /* linux or FreeBSD */ + + + /* TV channel table for Japan */ + BYTE vhf_table_1_JP[100] = { 0x08,0x08,0x09,0x0D,0x0D,0x0E,0x0E,0x0E, + 0x0F,0x0F,0x10,0x10,0x20,0x20,0x21,0x21, + 0x21,0x22,0x22,0x22,0x23,0x23,0x24,0x24, + 0x24,0x25,0x25,0x25,0x26,0x26,0x27,0x27, + 0x27,0x28,0x28,0x28,0x29,0x29,0x2A,0x2A, + 0x2A,0x2B,0x2B,0x2B,0x2C,0x2C,0x2D,0x2D, + 0x2D,0x2E,0x2E,0x2E,0x2F,0x2F,0x30,0x30, + 0x30,0x31,0x31,0x31,0x32,0x32,0x00,0x00, + 0x35,0x36,0x36,0x37,0x37,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00} ; + BYTE vhf_table_2_JP[100] = { 0x92,0xF2,0x52,0x92,0xF2,0x52,0xB2,0xF2, + 0x52,0xB2,0x12,0x72,0x52,0xB2,0x12,0x72, + 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, + 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, + 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, + 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, + 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x12,0x72, + 0xD2,0x32,0x92,0xF2,0x52,0xB2,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00} ; + BYTE vhf_table_3_JP[100] = { 0xA0,0xA0,0xA0,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30} ; + + /* TV channel table for US */ + BYTE vhf_table_1_US[100] = { 0x00,0x06,0x06,0x07,0x07,0x08,0x0D,0x0E, + 0x0E,0x0E,0x0F,0x0F,0x10,0x20,0x20,0x21, + 0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x24, + 0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x27, + 0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x2A, + 0x2A,0x2A,0x2B,0x2B,0x2B,0x2C,0x2C,0x2D, + 0x2D,0x2D,0x2E,0x2E,0x2E,0x2F,0x2F,0x30, + 0x30,0x30,0x31,0x31,0x31,0x32,0x32,0x33, + 0x33,0x33,0x34,0x34,0x34,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00} ; + BYTE vhf_table_2_US[100] = { 0x00,0x50,0xB0,0x10,0xB0,0x10,0xD0,0x30, + 0x90,0xF0,0x50,0xB0,0x10,0x50,0xB0,0x10, + 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, + 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, + 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, + 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, + 0x70,0xD0,0x30,0x90,0xF0,0x50,0xB0,0x10, + 0x70,0xB0,0x30,0x90,0xF0,0x50,0xB0,0x10, + 0x70,0xD0,0x30,0x90,0xF0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00} ; + BYTE vhf_table_3_US[100] = { 0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x30,0x30,0x30,0x30} ; + + WORD SccBase[NSCC]; + BYTE VPX_ver[NSCC]; + WORD MemWidth[NSCC], MemHeight[NSCC]; + BYTE MemStandard[NSCC]; + int Index; + + /*-------------------------------- WriteReg --------------------------------- + Sets a SCC/II register to a specified value. + Exit: None + -----------------------------------------------------------------------------*/ + void WriteReg(BYTE index, BYTE Value) + { + BYTE SavedIndex; + + SavedIndex = inp(SccBase[Index]+1); /* Save current index */ + outp(SccBase[Index]+1, index); + outp(SccBase[Index]+2, Value); + outp(SccBase[Index]+1, SavedIndex); /* Restore original index */ + } + + /*--------------------------------- ReadReg --------------------------------- + Gets a SCC/II register value. + Exit: Register value + -----------------------------------------------------------------------------*/ + BYTE ReadReg(BYTE index) + { + BYTE SavedIndex, Value; + + SavedIndex = inp(SccBase[Index]+1); /* Save current index. */ + outp(SccBase[Index]+1, index); + Value = inp(SccBase[Index]+2); + outp(SccBase[Index]+1, SavedIndex); /* Restore original index */ + + return(Value); + } + + /*---------------------------------- FPbusy ----------------------------------- + Send an 8-bit data streem (1 byte) starting from the MSb to the I2C bus. + Begins with a start protocol bit when the byte to be sent is a slave address. + -----------------------------------------------------------------------------*/ + BYTE FPbusy() + { + BYTE retries; + retries = 0; + while ((i2crd8(VPXI2C, FPSTA) & 0x4) && retries <= I2CRET) + retries++; + return(0); + } + + /*---------------------------------- i2cwr16 ---------------------------------- + Write a byte to the selected slave device, from 'addr', and to the selected + register, from 'subaddr'. + -----------------------------------------------------------------------------*/ + void i2cwr16(BYTE addr, BYTE subaddr, WORD data) + { + BYTE ready, retries; + + retries = 0; + do + { + ready = 1; + i2cstart (); + i2cwdata ((BYTE)((addr<<1)&0xFE)); + ready &= i2crack (); + i2cwdata (subaddr); + ready &= i2crack (); + i2cwdata ((BYTE)(data>>8)); + ready &= i2crack (); + i2cwdata ((BYTE)data); + ready &= i2crack (); + i2cstop (); + + if (!ready) + retries++; + } while (!ready && (retries <= I2CRET)); + } + + /*---------------------------------- i2crd16 ---------------------------------- + Read a byte from the selected slave device, from addr, and from the selected + register, from subaddr. + -----------------------------------------------------------------------------*/ + WORD i2crd16(BYTE addr, BYTE subaddr) + { + BYTE dataL, dataH; + BYTE ready, retries; + WORD i2csts; + + retries = 0; + do + { + ready = 1; + i2cstart (); /* send start protocol out to the slaves */ + i2cwdata ((BYTE)((addr<<1)&0xFE)); /* send a byte ('addr') to i2c bus.*/ + ready &= i2crack (); /* gets the acknowledge*/ + i2cwdata (subaddr); /* send a byte ('subaddr') to i2c bus.*/ + ready &= i2crack (); /* gets the acknowledge*/ + i2cstart (); /* send start protocol out to the slaves*/ + i2cwdata ((BYTE)((addr<<1)|0x01)); /* send a byte ('addr') to i2c bus.*/ + ready &= i2crack (); /* gets the acknowledge */ + dataH = i2crdata(); /* receive a byte from i2c bus (MSB)*/ + i2cwack (); /* gets the acknowledge*/ + dataL = i2crdata(); /* receive a byte from i2c bus (MSB)*/ + i2cwnack (); /* gets the acknowledge*/ + i2cstop (); /* sends a stop protocol to i2c bus*/ + i2csts=dataL+(dataH << 8); /* compose the WORD read from the bus */ + + if (!ready) + retries++; + } while (!ready && (retries <= I2CRET)); + + return (i2csts); + } + + /*----------------------------------- i2cwr8 ---------------------------------- + Write a byte to the selected slave device, from 'addr', and to the selected + register, from 'subaddr'. + -----------------------------------------------------------------------------*/ + void i2cwr8(BYTE addr, BYTE subaddr, BYTE data) + { + BYTE ready, retries; + + retries = 0; + do + { + ready = 1; + i2cstart (); + i2cwdata ((BYTE)((addr<<1)&0xFE)); + ready &= i2crack (); + i2cwdata (subaddr); + ready &= i2crack (); + i2cwdata (data); + ready &= i2crack (); + i2cstop (); + + if (!ready) + retries++; + } while (!ready && (retries <= I2CRET)); + } + + /*----------------------------------- i2crd8 ---------------------------------- + Read a byte from the selected slave device, from addr, and from the selected + register, from subaddr. + -----------------------------------------------------------------------------*/ + BYTE i2crd8(BYTE addr, BYTE subaddr) + { + BYTE data = 0; + BYTE i2csts; + BYTE ready, retries; + + retries = 0; + do + { + ready = 1; + i2cstart (); + i2cwdata ((BYTE)((addr<<1)&0xFE)); + i2crack (); + i2cwdata (subaddr); + i2crack (); + i2cstart (); + i2cwdata ((BYTE)((addr<<1)|0x01)); + i2crack (); + data = i2crdata(); + i2cwnack (); + i2cstop (); + i2csts = data; + + if (!ready) + retries++; + } while (!ready && (retries <= I2CRET)); + + return (i2csts); + } + + /*--------------------------------- i2cwdata ---------------------------------- + Send an 8-bit data streem (1 byte) starting from the MSb to the I2C bus. + Begins with a start protocol bit when the byte to be sent is a slave address. + -----------------------------------------------------------------------------*/ + void i2cwdata(BYTE data) + { + BYTE i; + + for(i = 0; i <= 7; i++) /* send out data stream*/ + { + i2cbwr(I2C_SDA, (BYTE)((data >> (7-i)) & 0x01)); /*MSbit goes out first*/ + i2cbwr(I2C_SCL, HICLK); + i2cwait(); + i2cbwr(I2C_SCL, LOCLK); + i2cbwr(I2C_SDA, HIDAT); + } + } + + /*--------------------------------- i2crdata ---------------------------------- + Receive an 8-bit data streem (1 byte) starting from the MSb from the I2C bus. + -----------------------------------------------------------------------------*/ + BYTE i2crdata() + { + BYTE i; + BYTE data = 0; + + for(i = 0; i <= 7; i++) /* send out data stream*/ + { + i2cbwr(I2C_SCL, HICLK); + i2cwait(); + data |= (i2cbrd(I2C_SDA) << (7-i)); /* MSbit comes first*/ + i2cbwr(I2C_SCL, LOCLK); + } + return(data); + } + + /*---------------------------------- i2cstart --------------------------------- + Send a start protocol out to the slaves. Start of protocol occurs on an + high-to-low transition of the data line while the clock is high. + -----------------------------------------------------------------------------*/ + void i2cstart() + { + i2cbwr (I2C_SCL, HICLK); + i2cbwr (I2C_SDA, LODAT); + i2cbwr (I2C_SCL, LOCLK); + i2cbwr (I2C_SDA, HIDAT); + } + + /*---------------------------------- i2cstop ---------------------------------- + Send stop protocol out to i2c slave. Stop protocol occurs on a positive + going transition of data line while clock line high. + -----------------------------------------------------------------------------*/ + void i2cstop() + { + i2cbwr(I2C_SDA, LODAT); + i2cbwr(I2C_SCL, HICLK); + i2cbwr(I2C_SDA, HIDAT); + } + + /*---------------------------------- i2cwack ---------------------------------- + Get an acknowledge back from a slave device + -----------------------------------------------------------------------------*/ + BYTE i2cwack() + { + i2cbwr (I2C_SDA, LODAT); + i2cbwr (I2C_SCL, HICLK); + i2cbwr (I2C_SCL, LOCLK); + i2cbwr (I2C_SDA, HIDAT); + return (0); + } + + /*--------------------------------- i2cwnack ---------------------------------- + Get an acknowledge back from a slave device + -----------------------------------------------------------------------------*/ + BYTE i2cwnack() + { + i2cbwr (I2C_SCL, HICLK); + i2cbwr (I2C_SCL, LOCLK); + return (0); + } + + /*--------------------------------- i2crack ----------------------------------- + Get an acknowledge back from a slave device + -----------------------------------------------------------------------------*/ + BYTE i2crack() + { + BYTE nack; + i2cbwr (I2C_SCL, HICLK); + nack = i2cbrd(I2C_SDA); + i2cbwr (I2C_SCL, LOCLK); + if (nack) + return (0); + else + return (1); + } + + /*------------------------------------ i2cbwr --------------------------------- + Writes a Bit into the I2C bus + -----------------------------------------------------------------------------*/ + void i2cbwr(BYTE type, BYTE data) + { + BYTE inbtmp; + + data = ~data & 0x01; /* invert data because the HW inverts again*/ + switch (type) + { + case I2C_SCL: + outp(SccBase[Index]+1,IOIF_REG); + inbtmp = (BYTE)~SCLW_MSK; + inbtmp &= inp(SccBase[Index]+2); /* read IOIF_REG masking SCLW*/ + inbtmp |= (data & 0x01); /* modify with the data bit*/ + outp(SccBase[Index]+2,inbtmp); /* and write back to the reg.*/ + break; + case I2C_SDA: + outp(SccBase[Index]+1,IOIF_REG); + inbtmp = (BYTE)~SDAW_MSK; + inbtmp &= inp(SccBase[Index]+2); /* read IOIF_REG masking SDAW*/ + inbtmp |= ((data & 0x01) << 1); /* modify with the data bit*/ + outp(SccBase[Index]+2,inbtmp); /* and write back to the reg.*/ + break; + } + } + + /*----------------------------------- i2cbrd ---------------------------------- + Reads a Bit from the I2C bus + -----------------------------------------------------------------------------*/ + BYTE i2cbrd(BYTE type) + { + BYTE inbtmp=0; + + switch (type) + { + case I2C_SCL: + outp (SccBase[Index]+1,IOIF_REG); /* read the status of SCL pin*/ + inbtmp = inp(SccBase[Index]+2) & SCLR_MSK; /* from the IOIF_REG*/ + inbtmp >>= 3; + break; + case I2C_SDA: + outp (SccBase[Index]+1,IOIF_REG); /* read the status of SDA pin*/ + inbtmp = inp(SccBase[Index]+2) & SDAR_MSK; /* from the IOIF_REG*/ + inbtmp >>= 4; + break; + } + return(inbtmp); + } + + /*---------------------------------- i2cwait ---------------------------------- + Wait for the slave is ready to accept next data + -----------------------------------------------------------------------------*/ + BYTE i2cwait() + { + while (i2cbrd(I2C_SCL) == 0); + return (0); + } + + #if 0 + /*------------------------------- SetTVStandard ------------------------------- + Initializes the VPX to decode a selected TV broadcast standard. + These will change among the VPX technical code versions! + -----------------------------------------------------------------------------*/ + void SetTVStandard(WORD stdsel, int index) + { + Index = index; + + switch (stdsel) + { + case PAL: + i2cwr8 (VPXI2C, STS, 0x01); /* select the PAL standard*/ + i2cwr8 (VPXI2C, DEEM, 0x08); + i2cwr8 (VPXI2C, LDF, 0x00); /* luma/chroma matching delay*/ + i2cwr8 (VPXI2C, YNF, 0x19); /* luma notch frequency*/ + i2cwr16 (VPXI2C, FPWR, 0x001B); /* standard = PAL*/ + i2cwr16 (VPXI2C, FPDAT, 0x0000); + i2cwr16 (VPXI2C, FPWR, 0x001C); + i2cwr16 (VPXI2C, FPDAT, 0x0000); + i2cwr16 (VPXI2C, FPWR, 0x0023); /* samples per line*/ + i2cwr16 (VPXI2C, FPDAT, 0x0510); + i2cwr16 (VPXI2C, FPWR, 0x0019); /* oscillator frequency*/ + i2cwr16 (VPXI2C, FPDAT, 0x0C69); + i2cwr16 (VPXI2C, FPWR, 0x001A); + i2cwr16 (VPXI2C, FPDAT, 0x0365); + i2cwr16 (VPXI2C, FPWR, 0x001F); /* chroma gain PLL*/ + i2cwr16 (VPXI2C, FPDAT, 0x0008); + i2cwr16 (VPXI2C, FPWR, 0x0033); /* vertical blanking*/ + i2cwr16 (VPXI2C, FPDAT, 0x026E); + i2cwr16 (VPXI2C, FPWR, 0x003A); + i2cwr16 (VPXI2C, FPDAT, 0x0135); + i2cwr16 (VPXI2C, FPWR, 0x0040); /* burst key set count*/ + i2cwr16 (VPXI2C, FPDAT, 0x00A0); + i2cwr16 (VPXI2C, FPWR, 0x0041); + i2cwr16 (VPXI2C, FPDAT, 0x00C0); + i2cwr16 (VPXI2C, FPWR, 0x00C0); + i2cwr16 (VPXI2C, FPDAT, 0x0001); + i2cwr16 (VPXI2C, FPWR, 0x00C1); + i2cwr16 (VPXI2C, FPDAT, 0x0135); + i2cwr16 (VPXI2C, FPWR, 0x00C2); + i2cwr16 (VPXI2C, FPDAT, 0x0140); + i2cwr16 (VPXI2C, FPWR, 0x00C3); + i2cwr16 (VPXI2C, FPDAT, 0x026E); + break; + case SECAM: + break; + case NTSC: + i2cwr8 (VPXI2C, STS, 0x02); /* select the NTSC standard*/ + i2cwr16 (VPXI2C, FPWR, 0x001B); /* standard = NTSC*/ + i2cwr16 (VPXI2C, FPDAT, 0x0001); + i2cwr16 (VPXI2C, FPWR, 0x001C); + i2cwr16 (VPXI2C, FPDAT, 0x0000); + i2cwr8 (VPXI2C, DEEM, 0x08); + i2cwr8 (VPXI2C, LDF, 0x00); /* luma/chroma matching delay*/ + i2cwr8 (VPXI2C, YNF, 0x39); /* luma notch frequency*/ + i2cwr16 (VPXI2C, FPWR, 0x00B2); + i2cwr16 (VPXI2C, FPDAT, 0x02DC); + i2cwr16 (VPXI2C, FPWR, 0x00A0); + i2cwr16 (VPXI2C, FPDAT, 0x0898); + i2cwr16 (VPXI2C, FPWR, 0x0027); + i2cwr16 (VPXI2C, FPDAT, 0x0054); + i2cwr16 (VPXI2C, FPWR, 0x0023); /* samples per line*/ + i2cwr16 (VPXI2C, FPDAT, 0x0507); + i2cwr16 (VPXI2C, FPWR, 0x0033); + i2cwr16 (VPXI2C, FPDAT, 0x020A); + i2cwr16 (VPXI2C, FPWR, 0x003A); + i2cwr16 (VPXI2C, FPDAT, 0x0103); + i2cwr16 (VPXI2C, FPWR, 0x0040); + i2cwr16 (VPXI2C, FPDAT, 0x008C); + i2cwr16 (VPXI2C, FPWR, 0x0041); + i2cwr16 (VPXI2C, FPDAT, 0x00AC); + i2cwr16 (VPXI2C, FPWR, 0x00C0); + i2cwr16 (VPXI2C, FPDAT, 0x0001); + i2cwr16 (VPXI2C, FPWR, 0x00C1); + i2cwr16 (VPXI2C, FPDAT, 0x0007); + i2cwr16 (VPXI2C, FPWR, 0x00C2); + i2cwr16 (VPXI2C, FPDAT, 0x0108); + i2cwr16 (VPXI2C, FPWR, 0x00C3); + i2cwr16 (VPXI2C, FPDAT, 0x010E); + i2cwr16 (VPXI2C, FPWR, 0x0010); + i2cwr16 (VPXI2C, FPDAT, 0x0022); + break; + case NTSCC: + break; + case NTSCK: + i2cwr8 (VPXI2C, STS, 0x01); /* select the NTSC standard*/ + i2cwr16 (VPXI2C, FPWR, 0x001B); /* standard = NTSC*/ + i2cwr16 (VPXI2C, FPDAT, 0x0001); + i2cwr16 (VPXI2C, FPWR, 0x001C); + i2cwr16 (VPXI2C, FPDAT, 0x0000); + i2cwr8 (VPXI2C, DEEM, 0x08); + i2cwr8 (VPXI2C, LDF, 0x00); + i2cwr8 (VPXI2C, YNF, 0x39); + i2cwr16 (VPXI2C, FPWR, 0x0023); + i2cwr16 (VPXI2C, FPDAT, 0x0507); + i2cwr16 (VPXI2C, FPWR, 0x0019); + i2cwr16 (VPXI2C, FPDAT, 0x00A5); + i2cwr16 (VPXI2C, FPWR, 0x001A); + i2cwr16 (VPXI2C, FPDAT, 0x02D4); + i2cwr16 (VPXI2C, FPWR, 0x001F); + i2cwr16 (VPXI2C, FPDAT, 0x0004); + i2cwr16 (VPXI2C, FPWR, 0x0033); + i2cwr16 (VPXI2C, FPDAT, 0x020A); + i2cwr16 (VPXI2C, FPWR, 0x003A); + i2cwr16 (VPXI2C, FPDAT, 0x0103); + i2cwr16 (VPXI2C, FPWR, 0x0040); + i2cwr16 (VPXI2C, FPDAT, 0x00A0); + i2cwr16 (VPXI2C, FPWR, 0x0041); + i2cwr16 (VPXI2C, FPDAT, 0x00C0); + i2cwr16 (VPXI2C, FPWR, 0x00C1); + i2cwr16 (VPXI2C, FPDAT, 0x0103); + i2cwr16 (VPXI2C, FPWR, 0x00C2); + i2cwr16 (VPXI2C, FPDAT, 0x010C); + i2cwr16 (VPXI2C, FPWR, 0x00C3); + i2cwr16 (VPXI2C, FPDAT, 0x020A); + break; + default: + break; + } + } + #endif + + /*------------------------------- SetTVChannel -------------------------------- + Selects a TV channel according the channel table. + This function have been designed around the Philips FI12XX family of tuners. + It calculates the tuning parameters and programs the tuner PLL and control + bytes. + -----------------------------------------------------------------------------*/ + BYTE SetTVChannel( BYTE tuntype, BYTE channel, BYTE fine, BYTE country, int index) + { + WORD u; + BYTE retries, ready, inbbtmp; + + Index = index; + + if (country) + u = (vhf_table_1_US[channel - 1] << 8 ) + + vhf_table_2_US[channel - 1] + fine; + else + u = (vhf_table_1_JP[channel - 1] << 8 ) + + vhf_table_2_JP[channel - 1] + fine; + + retries = 0; + do + { + ready = 1; + i2cstart (); + i2cwdata ((BYTE)((tuntype<<1)&0xFE)); + ready &= i2crack (); + i2cwdata ((BYTE)(( u >> 8 ) & 0x7F)); /* set DIV1*/ + ready &= i2crack (); + i2cwdata ((BYTE)(u & 0xFF)); /* set DIV2*/ + ready &= i2crack (); + i2cwdata (0x8E); /* set CB1*/ + ready &= i2crack (); + if (country) + i2cwdata (vhf_table_3_US[ channel - 1 ]); /* set CB2*/ + else + i2cwdata (vhf_table_3_JP[ channel - 1 ]); /* set CB2*/ + ready &= i2crack (); + i2cstop (); + + if (!ready) + retries++; + } while (!ready && (retries <= I2CRET)); + + i2cstart (); + i2cwdata ((BYTE)((tuntype<<1)|0x01)); + i2crack (); + inbbtmp = i2crdata(); + i2cwnack (); + i2cstop (); + + return (ready); + + } + + /**************************************************************************** + * Set up video filter + ****************************************************************************/ + void SetVideoFilter(WORD video_filter, int index) + { + + Index = index; + + switch (video_filter) + { + case 320: + /* these settings are to patch the wrong CCIR-601 pixel format into VPX */ + FPbusy(); + i2cwr8(VPXI2C, 0xD2, 0x00); /* luma prefilter selection*/ + i2cwr8(VPXI2C, 0xD3, 0x09); /* writes to the Filter-RAM location 1*/ + i2cwr8(VPXI2C, 0xD3, 0x17); /* writes to the Filter-RAM location 2*/ + i2cwr8(VPXI2C, 0xD3, 0xC6); /* writes to the Filter-RAM location 3*/ + i2cwr8(VPXI2C, 0xD3, 0xE7); /* writes to the Filter-RAM location 4*/ + i2cwr8(VPXI2C, 0xD3, 0x79); /* writes to the Filter-RAM location 5*/ + i2cwr8(VPXI2C, 0xD3, 0xAB); /* writes to the Filter-RAM location 6*/ + i2cwr8(VPXI2C, 0xD3, 0x69); /* writes to the Filter-RAM location 7*/ + i2cwr8(VPXI2C, 0xD3, 0x8C); /* writes to the Filter-RAM location 8*/ + i2cwr8(VPXI2C, 0xD3, 0x35); /* writes to the Filter-RAM location 9*/ + i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 10*/ + i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 11*/ + i2cwr8(VPXI2C, 0xD3, 0xAA); /* writes to the Filter-RAM location 12*/ + i2cwr8(VPXI2C, 0xD3, 0x32); /* writes to the Filter-RAM location 13*/ + i2cwr8(VPXI2C, 0xD3, 0x01); /* writes to the Filter-RAM location 14*/ + i2cwr8(VPXI2C, 0xD3, 0x20); /* writes to the Filter-RAM location 15*/ + i2cwr8(VPXI2C, 0xD0, 0x60); /* RAM and I2C override selection*/ + break; + + case 640: + /* The following values are to patch the wrong CCIR-601 pixel format.*/ + /* These value settings refer to the 640 NPIX upper bound */ + FPbusy(); + i2cwr8(VPXI2C, 0xD2, 0x00); /* luma prefilter selection*/ + i2cwr8(VPXI2C, 0xD3, 0x81); /* writes to the Filter-RAM location 1*/ + i2cwr8(VPXI2C, 0xD3, 0x96); /* writes to the Filter-RAM location 2*/ + i2cwr8(VPXI2C, 0xD3, 0x06); /* writes to the Filter-RAM location 3*/ + i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 4*/ + i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 5*/ + i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 6*/ + i2cwr8(VPXI2C, 0xD3, 0x00); /* writes to the Filter-RAM location 7*/ + i2cwr8(VPXI2C, 0xD3, 0x34); /* writes to the Filter-RAM location 8*/ + i2cwr8(VPXI2C, 0xD3, 0xD0); /* writes to the Filter-RAM location 9*/ + i2cwr8(VPXI2C, 0xD3, 0x02); /* writes to the Filter-RAM location 10*/ + i2cwr8(VPXI2C, 0xD3, 0xC8); /* writes to the Filter-RAM location 11*/ + i2cwr8(VPXI2C, 0xD3, 0x86); /* writes to the Filter-RAM location 12*/ + i2cwr8(VPXI2C, 0xD3, 0x32); /* writes to the Filter-RAM location 13*/ + i2cwr8(VPXI2C, 0xD3, 0x01); /* writes to the Filter-RAM location 14*/ + i2cwr8(VPXI2C, 0xD3, 0x10); /* writes to the Filter-RAM location 15*/ + i2cwr8(VPXI2C, 0xD0, 0x60); /* RAM and I2C override selection*/ + break; + } + + } + + /*****************************************************************************/ + void SetVPXColor(BYTE brightness, BYTE contrast, WORD saturation, WORD hue, int index) + { + Index = index; + + FPbusy(); + i2cwr8 (VPXI2C, CBM_BRI, (BYTE)(brightness-128)); + + FPbusy(); + /* i2cwr8 (VPXI2C, CBM_CON, (contrast & 0x3f) | noise_shaping);*/ + i2cwr8 (VPXI2C, CBM_CON, contrast); + + FPbusy(); + i2cwr16 (VPXI2C, FPWR, ACCREF); + i2cwr16 (VPXI2C, FPDAT, saturation); + + FPbusy(); + i2cwr16(VPXI2C, FPWR, 0x001C); /* TINT color hue*/ + i2cwr16(VPXI2C, FPDAT, hue-2048); + + + /* brightness = def_brightness; + SetBrightness(); + contrast = def_contrast; + noise_shaping = def_noise_shaping; + SetContrast(); + saturation = def_saturation; + SetSaturation(); + hue = def_hue; + SetHue(); + SetFormat(); + */ + } + + /**************************************************************************** + ** Initialize VPX + ****************************************************************************/ + void InitVPX(WORD IOBase, BYTE Standard, BYTE Inbut, WORD Width, + WORD Height, BYTE SkipRate, BYTE DataFormat, int index) + { + BYTE inbbtmp; + + Index = index; + SccBase[Index] = IOBase; + MemWidth[Index] = Width; + MemHeight[Index] = Height; + MemStandard[Index] = Standard; + + /* get VPX version*/ + if (0xEC == i2crd8(VPXI2C, I2C_ID0) && + 0x80 == i2crd8(VPXI2C, I2C_ID1) && + 0x46 == i2crd8(VPXI2C, I2C_ID2)) { + VPX_ver[Index] = 1; /* VPX is C4 version*/ + } else { + VPX_ver[Index] = 0; /* VPX is earlier than C4;*/ + } + + /* set data format*/ + i2cwr8(VPXI2C, FORMAT, (BYTE)(0xb0 | (DataFormat & 0x7))); + + if (!VPX_ver[Index]) + SetVideoFilter(640, index); + + if (Standard == 1) /* NTSC*/ + { + if (Height > 240) + Height = (Height + 1)/2; + + if (!VPX_ver[Index]) + { + i2cwr8(VPXI2C, STS, 0x02); /* select the NTSC standard*/ + i2cwr16(VPXI2C, FPWR, 0x001C); /* TINT color hue*/ + i2cwr16(VPXI2C, FPDAT, 0x0000); + FPbusy(); + i2cwr8(VPXI2C, DEEM, 0x08); + i2cwr8(VPXI2C, LDF, 0x06); /* luma/chroma matching delay*/ + i2cwr8(VPXI2C, YNF, 0x39); /* luma notch frequency*/ + + /* modification for TC05 */ + i2cwr16(VPXI2C, FPWR, VSDT); + i2cwr16(VPXI2C, FPDAT, 524); + FPbusy(); + i2cwr16(VPXI2C, FPWR, AGCREF); + i2cwr16(VPXI2C, FPDAT, 732); + FPbusy(); + i2cwr16(VPXI2C, FPWR, ACCREF); + i2cwr16(VPXI2C, FPDAT, 2263); + FPbusy(); + i2cwr16(VPXI2C, FPWR, CLPPK); + i2cwr16(VPXI2C, FPDAT, 90); + FPbusy(); + i2cwr16(VPXI2C, FPWR, SPL); + i2cwr16(VPXI2C, FPDAT, 1287); + FPbusy(); + i2cwr16(VPXI2C, FPWR, BKS); + i2cwr16(VPXI2C, FPDAT, 140); + FPbusy(); + i2cwr16(VPXI2C, FPWR, BKR); + i2cwr16(VPXI2C, FPDAT, 204); + FPbusy(); + i2cwr16(VPXI2C, FPWR, SDT); + i2cwr16(VPXI2C, FPDAT, 1); + FPbusy(); + + /* ### KS 05.11.94*/ + + /* write VREF timing for TC05*/ + /**/ + i2cwr16(VPXI2C, FPWR, 0x00C0); + i2cwr16(VPXI2C, FPDAT, 0x0001); + FPbusy(); + i2cwr16(VPXI2C, FPWR, 0x00C1); + i2cwr16(VPXI2C, FPDAT, 0x0007); + FPbusy(); + i2cwr16(VPXI2C, FPWR, 0x00C2); + i2cwr16(VPXI2C, FPDAT, 0x0108); + FPbusy(); + i2cwr16(VPXI2C, FPWR, 0x00C3); + i2cwr16(VPXI2C, FPDAT, 0x010E); + FPbusy(); + /* VREF TC02 compatible mode*/ + i2cwr16(VPXI2C, FPWR, 0x00F0); + i2cwr16(VPXI2C, FPDAT, 0x2); + FPbusy(); + } + else + { + i2cwr16 (VPXI2C, FPWR, ACCREF); + i2cwr16 (VPXI2C, FPDAT, 0x700); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, TVSTD); + i2cwr16 (VPXI2C, FPDAT, 0x13); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, 0x00C2); + i2cwr16 (VPXI2C, FPDAT, 0x0096); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, 0x00C1); + i2cwr16 (VPXI2C, FPDAT, 0x0055); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, VSDT); + i2cwr16 (VPXI2C, FPDAT, 0x20a); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, IF1IF2); + i2cwr16 (VPXI2C, FPDAT, 0x29c); + FPbusy(); + + /* set up for VPX C4*/ + i2cwr8 (VPXI2C, REFSIG, 0x06); /* C4 VREF,HREF */ + FPbusy(); + /* initialize VPX to RGB 565 16 bit Inverse Gamma, dither enabled*/ + /* i2cwr8 (VPXI2C, FORMAT, 0xf6);*/ + i2cwr8(VPXI2C, FORMAT_C4, (BYTE)(0xf0 | (DataFormat & 0x7))); + FPbusy(); + i2cwr8 (VPXI2C, OFIFO, 0x0b); + FPbusy(); + i2cwr8 (VPXI2C, OMUX, 0x88); + FPbusy(); + i2cwr8 (VPXI2C, OENA, 0x5b); + FPbusy(); + } + } + else + { + if (Height > 290) + Height = (Height + 1)/2; + + if (!VPX_ver[Index]) + { + i2cwr8(VPXI2C, STS, 0x01); /* select the PAL standard*/ + i2cwr8(VPXI2C, DEEM, 0x08); + i2cwr8(VPXI2C, LDF, 0x06); /* luma/chroma matching delay*/ + i2cwr8(VPXI2C, YNF, 25); /* luma notch frequency*/ + + /* ### KS 05.11.94*/ + /* modification for TC05*/ + i2cwr16(VPXI2C, FPWR, VSDT); + i2cwr16(VPXI2C, FPDAT, 624); + FPbusy(); + i2cwr16(VPXI2C, FPWR, AGCREF); + i2cwr16(VPXI2C, FPDAT, 768); + FPbusy(); + i2cwr16(VPXI2C, FPWR, ACCREF); + i2cwr16(VPXI2C, FPDAT, 2263); + FPbusy(); + i2cwr16(VPXI2C, FPWR, CLPPK); + i2cwr16(VPXI2C, FPDAT, 54); + FPbusy(); + i2cwr16(VPXI2C, FPWR, SPL); + i2cwr16(VPXI2C, FPDAT, 1296); + FPbusy(); + i2cwr16(VPXI2C, FPWR, BKS); + i2cwr16(VPXI2C, FPDAT, 140); + FPbusy(); + i2cwr16(VPXI2C, FPWR, BKR); + i2cwr16(VPXI2C, FPDAT, 204); + FPbusy(); + i2cwr16(VPXI2C, FPWR, SDT); + i2cwr16(VPXI2C, FPDAT, 0); + FPbusy(); + + /* ### KS 05.11.94*/ + /* write VREF timing for TC05*/ + /**/ + i2cwr16(VPXI2C, FPWR, 0x00C0); + i2cwr16(VPXI2C, FPDAT, 0x0001); + FPbusy(); + i2cwr16(VPXI2C, FPWR, 0x00C1); + i2cwr16(VPXI2C, FPDAT, 0x0007); + FPbusy(); + i2cwr16(VPXI2C, FPWR, 0x00C2); + i2cwr16(VPXI2C, FPDAT, 0x013a); + FPbusy(); + i2cwr16(VPXI2C, FPWR, 0x00C3); + i2cwr16(VPXI2C, FPDAT, 0x0140); + FPbusy(); + /* VREF TC02 compatible mode*/ + i2cwr16(VPXI2C, FPWR, 0x00F0); + i2cwr16(VPXI2C, FPDAT, 0x2); + FPbusy(); + } + else + { + i2cwr16 (VPXI2C, FPWR, ACCREF); + i2cwr16 (VPXI2C, FPDAT, 0x7d0); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, TVSTD); + i2cwr16 (VPXI2C, FPDAT, 0x11); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, 0x00C2); + i2cwr16 (VPXI2C, FPDAT, 0x0096); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, 0x00C1); + i2cwr16 (VPXI2C, FPDAT, 0x0055); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, VSDT); + i2cwr16 (VPXI2C, FPDAT, 0x26e); + FPbusy(); + i2cwr16 (VPXI2C, FPWR, IF1IF2); + i2cwr16 (VPXI2C, FPDAT, 0x29c); + FPbusy(); + + /* set up for VPX C4*/ + i2cwr8 (VPXI2C, REFSIG, 0x06); /* C4 VREF,HREF */ + FPbusy(); + /* initialize VPX to RGB 565 16 bit Inverse Gamma, dither enabled*/ + /* i2cwr8 (VPXI2C, FORMAT, 0xf6);*/ + i2cwr8(VPXI2C, FORMAT_C4, (BYTE)(0xf0 | (DataFormat & 0x7))); + FPbusy(); + i2cwr8 (VPXI2C, OFIFO, 0x0b); + FPbusy(); + i2cwr8 (VPXI2C, OMUX, 0x88); + FPbusy(); + i2cwr8 (VPXI2C, OENA, 0x5b); + FPbusy(); + } + } + + if (!VPX_ver[Index]) + do { + FPbusy(); + i2cwr16(VPXI2C, FPRD, CWDWD); + } while (i2crd16 (VPXI2C, FPDAT) & 0x30); + else + do { + FPbusy(); + i2cwr16(VPXI2C, FPRD, CWDWD_C4); + } while (i2crd16 (VPXI2C, FPDAT) & 0x72); + + outp(IOBase, 0x00); /* clear the status register*/ + while ((inp(IOBase) & 0x40)); + + /*-------------------------------------------------------------------*/ + switch (Inbut) + { + case 0: /* switch to Video Inbut 1 */ + FPbusy(); + i2cwr8(VPXI2C, AFEND, 0x02); + inbbtmp = i2crd8 (VPXI2C, STS); + i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp & 0xFB)); + break; + case 1: /* switch to Video Inbut 2 */ + FPbusy(); + i2cwr8(VPXI2C, AFEND, 0x01); + inbbtmp = i2crd8 (VPXI2C, STS); + i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp & 0xFB)); + break; + case 2: /* switch to Video Inbut 3 */ + FPbusy(); + i2cwr8(VPXI2C, AFEND, 0x00); + inbbtmp = i2crd8 (VPXI2C, STS); + i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp & 0xFB)); + break; + case 3: /* switch to S-Video Inbut */ + FPbusy(); + i2cwr8(VPXI2C, AFEND, 0x08); + inbbtmp = i2crd8 (VPXI2C, STS); + i2cwr8(VPXI2C, STS, (BYTE)(inbbtmp | 0x04)); + break; + } + + + /*---------------------------------------------------------------------*/ + outp(IOBase+1, 0x04); + /* if (mem_wait_states)*/ + /* outp(IOBase+3, 0x4D); // enable terminator resistors (SIC) */ + /* else*/ + outp(IOBase+3, 0x0D); /* enable terminator resistors (SIC)*/ + + outp(IOBase+1, 0x04); + /* skip 1 field*/ + outp(IOBase+2, (BYTE)((inp(IOBase+2) & 0x1f) | (SkipRate << 5))); + + SetVPXRect(Width, Height, index); + } + + /**************************************************************************** + ** Set VPX rect + *****************************************************************************/ + void SetVPXRect(WORD Width, WORD Height, int index) + { + + Index = index; + MemWidth[Index] = Width; + MemHeight[Index] = Height; + + if (Height > 240) + Height = (Height + 1)/2; + + if (MemStandard[Index] == 1) + { + /* set the source video window */ + FPbusy(); + i2cwr16(VPXI2C, FPWR, VBEG1); + i2cwr16(VPXI2C, FPDAT, 12); + FPbusy(); + i2cwr16(VPXI2C, FPWR, VLINEI1); + i2cwr16(VPXI2C, FPDAT, 248); + FPbusy(); + i2cwr16(VPXI2C, FPWR, VLINEO1); + i2cwr16(VPXI2C, FPDAT, Height+8); + FPbusy(); + i2cwr16(VPXI2C, FPWR, HBEG1); + i2cwr16(VPXI2C, FPDAT, 10); + FPbusy(); + i2cwr16(VPXI2C, FPWR, HLEN1); + i2cwr16(VPXI2C, FPDAT, Width); + FPbusy(); + i2cwr16(VPXI2C, FPWR, NPIX1); + i2cwr16(VPXI2C, FPDAT, Width + 10); + + FPbusy(); /* switches off Window 2*/ + i2cwr16(VPXI2C, FPWR, VLINEI2); + i2cwr16(VPXI2C, FPDAT, 0); + + FPbusy(); + if (!VPX_ver[Index]) + { + i2cwr16(VPXI2C, FPWR, CWDWD); + i2cwr16(VPXI2C, FPDAT, 0x0032); + } + else + { + i2cwr16(VPXI2C, FPWR, CWDWD_C4); + i2cwr16(VPXI2C, FPDAT, 0x0077); + } + } + else + { + /* set the source video window */ + FPbusy(); + i2cwr16(VPXI2C, FPWR, VBEG1); + i2cwr16(VPXI2C, FPDAT, 12); + FPbusy(); + i2cwr16(VPXI2C, FPWR, VLINEI1); + i2cwr16(VPXI2C, FPDAT, 298); + FPbusy(); + i2cwr16(VPXI2C, FPWR, VLINEO1); + i2cwr16(VPXI2C, FPDAT, Height+8); + FPbusy(); + i2cwr16(VPXI2C, FPWR, HBEG1); + i2cwr16(VPXI2C, FPDAT, 15); + FPbusy(); + i2cwr16(VPXI2C, FPWR, HLEN1); + i2cwr16(VPXI2C, FPDAT, Width); + FPbusy(); + i2cwr16(VPXI2C, FPWR, NPIX1); + i2cwr16(VPXI2C, FPDAT, Width + 10); + + FPbusy(); /* switches off Window 2*/ + i2cwr16(VPXI2C, FPWR, VLINEI2); + i2cwr16(VPXI2C, FPDAT, 0); + + FPbusy(); + if (!VPX_ver[Index]) + { + i2cwr16(VPXI2C, FPWR, CWDWD); + i2cwr16(VPXI2C, FPDAT, 0x0032); + } + else + { + i2cwr16(VPXI2C, FPWR, CWDWD_C4); + i2cwr16(VPXI2C, FPDAT, 0x0077); + } + } + + if (!VPX_ver[Index]) + do { + FPbusy(); + i2cwr16(VPXI2C, FPRD, CWDWD); + } while (i2crd16 (VPXI2C, FPDAT) & 0x30); + else + do { + FPbusy(); + i2cwr16(VPXI2C, FPRD, CWDWD_C4); + } while (i2crd16 (VPXI2C, FPDAT) & 0x72); + + while (inp(SccBase[Index]) & 0x20); + while (!(inp(SccBase[Index]) & 0x20)); + while (inp(SccBase[Index]) & 0x20); + while (!(inp(SccBase[Index]) & 0x20)); + } + + /**************************************************************************** + ** Freeze VPX + *****************************************************************************/ + void FreezeVPX(BYTE Action, int index) + { + static WORD CopyWidth; + static WORD CopyHeight; + + Index = index; + + switch (Action) + { + case 0: CopyWidth = MemWidth[Index]; + CopyHeight = MemHeight[Index]; + SetVPXRect(20, 0, index); + break; + case 1: SetVPXRect(CopyWidth, CopyHeight, index); + break; + case 2: outp(SccBase[Index]+1, 0x04); + outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) | 0x10)); + while (inp(SccBase[Index]) & 0x20); + break; + case 3: outp(SccBase[Index]+1, 0x04); + outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) & 0xef)); + break; + } + } + + /**************************************************************************** + ** Set Format + ***************************************************************************/ + + void SetVPXFmt(BYTE DataFormat, int index) + { + Index = index; + + i2cwr8(VPXI2C, FORMAT, (BYTE)(0xb0 | (DataFormat & 0x7))); + } + + /**************************************************************************** + ** Set IRQ state + ***************************************************************************/ + void SetIRQState(BYTE State, int index) + { + + Index = index; + + /* outp(SccBase[Index]+1, 0x04);*/ + switch (State) + { + case 0: outp(SccBase[Index]+1, 0x04); + outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) & 0xfd)); + break; + case 1: outp(SccBase[Index]+1, 0x04); + outp(SccBase[Index]+2, (BYTE)(inp(SccBase[Index]+2) | 2)); + break; + case 2: outp(SccBase[Index], (BYTE)(inp(SccBase[Index]) & 0xfd)); + break; + } + } + + /**************************************************************************** + ** Set IRQ state + ****************************************************************************/ + void WaitCapture(BYTE Wait, int index) + { + short i; + + Index = index; + + for (i=0;i #include #include ! #include #include #include #include #include ! #include ! #include #include - #include #include #ifdef DEVFS #include #endif --- 63,77 ---- #include #include #include ! #include #include #include #include #include ! #include #include #include + #include #ifdef DEVFS #include #endif *************** *** 81,96 **** #include #include #include #ifdef COM_ESP #include #endif #include #include "card.h" #if NCARD > 0 #include - #include #include #endif --- 81,100 ---- #include #include #include + /* #include */ #ifdef COM_ESP #include #endif #include + #ifdef NECMG + #include + #endif /* NECMG */ + #include "card.h" #if NCARD > 0 #include #include #endif *************** *** 119,126 **** --- 123,141 ---- #define COM_NOTAST4(dev) ((dev)->id_flags & 0x04) #endif /* COM_MULTIPORT */ + #define COM_CONSOLE(dev) ((dev)->id_flags & 0x10) + #define COM_FORCECONSOLE(dev) ((dev)->id_flags & 0x20) + #define COM_LLCONSOLE(dev) ((dev)->id_flags & 0x40) #define COM_LOSESOUTINTS(dev) ((dev)->id_flags & 0x08) #define COM_NOFIFO(dev) ((dev)->id_flags & 0x02) + #define COM_IRQBUG(dev) ((dev)->id_flags & 0x10) + #define COM_NOTST3(dev) ((dev)->id_flags & 0x10000) + #define COM_ST16650A(dev) ((dev)->id_flags & 0x20000) + #define COM_C_NOPROBE (0x40000) + #define COM_NOPROBE(dev) ((dev)->id_flags & COM_C_NOPROBE) + #define COM_C_IIR_TXRDYBUG (0x80000) + #define COM_IIR_TXRDYBUG(dev) ((dev)->id_flags & COM_C_IIR_TXRDYBUG) + #define COM_FIFOSIZE(dev) (((dev)->id_flags & 0xff000000) >> 24) #define com_scr 7 /* scratch register for 16450-16550 (R/W) */ *************** *** 188,193 **** --- 203,209 ---- /* com device structure */ struct com_s { + u_int id_flags; /* Copy isa device falgas */ u_char state; /* miscellaneous flag bits */ bool_t active_out; /* nonzero if the callout device is open */ u_char cfcr_image; /* copy of value written to CFCR */ *************** *** 197,202 **** --- 213,219 ---- u_char extra_state; /* more flag bits, separate for order trick */ u_char fifo_image; /* copy of value written to FIFO */ bool_t hasfifo; /* nonzero for 16550 UARTs */ + bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ bool_t loses_outints; /* nonzero if device loses output interrupts */ u_char mcr_image; /* copy of value written to MCR */ #ifdef COM_MULTIPORT *************** *** 238,243 **** --- 255,261 ---- Port_t modem_ctl_port; Port_t line_status_port; Port_t modem_status_port; + Port_t intr_ctl_port; /* Ports of IIR register */ struct tty *tp; /* cross reference */ *************** *** 289,294 **** --- 307,313 ---- */ /* Interrupt handling entry point. */ + inthand2_t siointrts; void siopoll __P((void)); /* Device switch entry points. */ *************** *** 379,397 **** { -1, -1 } }; #ifdef COM_ESP /* XXX configure this properly. */ - static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; #endif #if NCARD > 0 /* * PC-Card (PCMCIA) specific code. */ ! static int sioinit(struct pccard_devinfo *); /* init device */ ! static void siounload(struct pccard_devinfo *); /* Disable driver */ ! static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ static struct pccard_device sio_info = { driver_name, --- 398,481 ---- { -1, -1 } }; + static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; + #ifdef COM_ESP /* XXX configure this properly. */ static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; #endif + #ifdef NECMG + static struct isa_device necmg_isa_comdev[NSIO]; + #endif /* NECMG */ + + /* + * handle sysctl read/write requests for console speed + * + * In addition to setting comdefaultrate for I/O through /dev/console, + * also set the initial and lock values for the /dev/ttyXX device + * if there is one associated with the console. Finally, if the /dev/tty + * device has already been open, change the speed on the open running port + * itself. + */ + + static int + sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS + { + int error, s; + speed_t newspeed; + struct com_s *com; + struct tty *tp; + + newspeed = comdefaultrate; + + error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req); + if (error || !req->newptr) + return (error); + + comdefaultrate = newspeed; + + if (comconsole < 0) /* serial console not selected? */ + return (0); + + com = com_addr(comconsole); + if (!com) + return (ENXIO); + + /* + * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX + * (note, the lock rates really are boolean -- if non-zero, disallow + * speed changes) + */ + com->it_in.c_ispeed = com->it_in.c_ospeed = + com->lt_in.c_ispeed = com->lt_in.c_ospeed = + com->it_out.c_ispeed = com->it_out.c_ospeed = + com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate; + + /* + * if we're open, change the running rate too + */ + tp = com->tp; + if (tp && (tp->t_state & TS_ISOPEN)) { + tp->t_termios.c_ispeed = + tp->t_termios.c_ospeed = comdefaultrate; + s = spltty(); + error = comparam(tp, &tp->t_termios); + splx(s); + } + return error; + } + + SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW, + 0, 0, sysctl_machdep_comdefaultrate, "I", ""); + #if NCARD > 0 /* * PC-Card (PCMCIA) specific code. */ ! static int sioinit __P((struct pccard_devinfo *)); ! static void siounload __P((struct pccard_devinfo *)); ! static int card_intr __P((struct pccard_devinfo *)); static struct pccard_device sio_info = { driver_name, *************** *** 405,410 **** --- 489,496 ---- DATA_SET(pccarddrv_set, sio_info); + static int pccard_mode[NSIO]; + /* * Initialize the device - called from Slot manager. */ *************** *** 412,423 **** sioinit(struct pccard_devinfo *devi) { /* validate unit number. */ ! if (devi->isahd.id_unit >= (NSIOTOT)) return(ENODEV); /* Make sure it isn't already probed. */ ! if (com_addr(devi->isahd.id_unit)) return(EBUSY); /* * Probe the device. If a value is returned, the * device was found at the location. --- 498,516 ---- sioinit(struct pccard_devinfo *devi) { + int unit = devi->pd_unit; + /* validate unit number. */ ! if (unit >= (NSIOTOT)) return(ENODEV); + pccard_mode[unit] = 1; /* Make sure it isn't already probed. */ ! if (com_addr(unit)) return(EBUSY); + + /* It's already probed as serial by Upper */ + devi->isahd.id_flags |= COM_C_NOPROBE; + /* * Probe the device. If a value is returned, the * device was found at the location. *************** *** 443,457 **** siounload(struct pccard_devinfo *devi) { struct com_s *com; ! com = com_addr(devi->isahd.id_unit); if (!com->iobase) { ! printf("sio%d already unloaded!\n",devi->isahd.id_unit); return; } if (com->tp && (com->tp->t_state & TS_ISOPEN)) { com->gone = 1; ! printf("sio%d: unload\n", devi->isahd.id_unit); com->tp->t_gen++; ttyclose(com->tp); ttwakeup(com->tp); --- 536,553 ---- siounload(struct pccard_devinfo *devi) { struct com_s *com; + int unit = devi->pd_unit; ! if (unit >= (NSIOTOT)) ! return; ! com = com_addr(unit); if (!com->iobase) { ! printf("sio%d already unloaded!\n", unit); return; } if (com->tp && (com->tp->t_state & TS_ISOPEN)) { com->gone = 1; ! printf("sio%d: unload\n", unit); com->tp->t_gen++; ttyclose(com->tp); ttwakeup(com->tp); *************** *** 460,466 **** com_addr(com->unit) = NULL; bzero(com, sizeof *com); free(com,M_TTYS); ! printf("sio%d: unload,gone\n", devi->isahd.id_unit); } } --- 556,563 ---- com_addr(com->unit) = NULL; bzero(com, sizeof *com); free(com,M_TTYS); ! printf("sio%d: unload,gone\n", unit); ! } } *************** *** 473,481 **** { struct com_s *com; ! com = com_addr(devi->isahd.id_unit); if (com && !com->gone) ! siointr1(com_addr(devi->isahd.id_unit)); return(1); } #endif /* NCARD > 0 */ --- 570,578 ---- { struct com_s *com; ! com = com_addr(devi->pd_unit); if (com && !com->gone) ! siointr1(com_addr(devi->pd_unit)); return(1); } #endif /* NCARD > 0 */ *************** *** 486,491 **** --- 583,589 ---- { static bool_t already_init; bool_t failures[10]; + Port_t *com_ptr; int fn; struct isa_device *idev; Port_t iobase; *************** *** 495,500 **** --- 593,618 ---- int result; struct isa_device *xdev; + #if 0 + int sio_irq_bug = 0; + #endif + #if NCARD > 0 + int probe_pccard = pccard_mode[dev->id_unit]; + int iperror = 0; + #endif /* NCARD > 0 */ + #ifdef NECMG + int com_power = -1; + #endif /* NECMG */ + + #if NCARD > 0 + probe_pccard = pccard_mode[dev->id_unit]; + #endif /* NCARD > 0 */ + #if 0 + #ifdef SIO_IRQ_BUG + sio_irq_bug = 1; + #endif /* SIO_IRQ_BUG */ + #endif + if (!already_init) { /* * Turn off MCR_IENABLE for all likely serial ports. An unused *************** *** 502,513 **** * from any used port that shares the interrupt vector. * XXX the gate enable is elsewhere for some multiports. */ ! for (xdev = isa_devtab_tty; xdev->id_driver != NULL; xdev++) ! if (xdev->id_driver == &siodriver && xdev->id_enabled) ! outb(xdev->id_iobase + com_mcr, 0); already_init = TRUE; } /* * If the device is on a multiport card and has an AST/4 * compatible interrupt control register, initialize this --- 620,638 ---- * from any used port that shares the interrupt vector. * XXX the gate enable is elsewhere for some multiports. */ ! for (com_ptr = likely_com_ports; ! com_ptr < &likely_com_ports[sizeof likely_com_ports ! / sizeof likely_com_ports[0]]; ! ++com_ptr) ! outb(*com_ptr + com_mcr, 0); already_init = TRUE; } + if (COM_LLCONSOLE(dev)) { + printf("sio%d: reserved for low-level i/o\n", dev->id_unit); + return (0); + } + /* * If the device is on a multiport card and has an AST/4 * compatible interrupt control register, initialize this *************** *** 541,546 **** --- 666,689 ---- bzero(failures, sizeof failures); iobase = dev->id_iobase; + #ifdef NECMG + if (dev->id_unit != comconsole) { + if (&necmg_isa_comdev[dev->id_unit] != dev) { + /* called from isa.c */ + necmg_isa_comdev[dev->id_unit] = *dev; + if (dev->id_iobase == NECMG_IO_COM1) { + com_power = NECMG_COM1; + } else + if (dev->id_iobase == NECMG_IO_COM3) { + com_power = NECMG_COM3; + } + } + } + if (0 < com_power) { + necmg_com_power(com_power, 1 /* ON */); + } + #endif /* NECMG */ + /* * We don't want to get actual interrupts, just masked ones. * Interrupts from this line should already be masked in the ICU, *************** *** 560,570 **** * XXX what about the UART bug avoided by waiting in comparam()? * We don't want to to wait long enough to drain at 2 bps. */ ! outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); ! outb(iobase + com_dlbl, COMBRD(9600) & 0xff); ! outb(iobase + com_dlbh, (u_int) COMBRD(9600) >> 8); ! outb(iobase + com_cfcr, CFCR_8BITS); ! DELAY((16 + 1) * 1000000 / (9600 / 10)); /* * Enable the interrupt gate and disable device interupts. This --- 703,717 ---- * XXX what about the UART bug avoided by waiting in comparam()? * We don't want to to wait long enough to drain at 2 bps. */ ! if (iobase == siocniobase) ! DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); ! else { ! outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); ! outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff); ! outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8); ! outb(iobase + com_cfcr, CFCR_8BITS); ! DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); ! } /* * Enable the interrupt gate and disable device interupts. This *************** *** 601,607 **** * it's unlikely to do more than allow the null byte out. */ outb(iobase + com_data, 0); ! DELAY((1 + 2) * 1000000 / (9600 / 10)); /* * Turn off loopback mode so that the interrupt gate works again --- 748,754 ---- * it's unlikely to do more than allow the null byte out. */ outb(iobase + com_data, 0); ! DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); /* * Turn off loopback mode so that the interrupt gate works again *************** *** 613,618 **** --- 760,796 ---- /* EXTRA DELAY? */ outb(iobase + com_mcr, mcr_image); + /* + * It's a definitly Serial PCMCIA(16550A), but still be required + * for IIR_TXRDY implementation ( Palido 321s, DC-1S... ) + */ + if ( COM_NOPROBE(dev) ) { + /* Reading IIR register twice */ + for ( fn = 0; fn < 2; fn ++ ) { + DELAY(10000); + failures[6] = inb(iobase + com_iir); + } + /* Check IIR_TXRDY clear ? */ + result = IO_COMSIZE; + if ( failures[6] & IIR_TXRDY ) { + /* Nop, Double check with clearing IER */ + outb(iobase + com_ier, 0); + if ( inb(iobase + com_iir) & IIR_NOPEND ) { + /* Ok. we're familia this gang */ + dev->id_flags |= COM_C_IIR_TXRDYBUG; /* Set IIR_TXRDYBUG */ + } else { + /* Unknow, Just omit this chip.. XXX*/ + result = 0; + } + } else { + /* OK. this is well-known guys */ + dev->id_flags &= ~COM_C_IIR_TXRDYBUG; /*Clear IIR_TXRDYBUG*/ + } + outb(iobase + com_cfcr, CFCR_8BITS); + enable_intr(); + return( result ); + } + /* * Check that * o the CFCR, IER and MCR in UART hold the values written to them *************** *** 621,636 **** --- 799,872 ---- * o an output interrupt is generated and its vector is correct. * o the interrupt goes away when the IIR in the UART is read. */ + disable_intr(); /* EXTRA DELAY? */ failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS; failures[1] = inb(iobase + com_ier) - IER_ETXRDY; failures[2] = inb(iobase + com_mcr) - mcr_image; DELAY(10000); /* Some internal modems need this time */ irqmap[1] = isa_irq_pending(); + #if 0 /* isn't this code still necessary? (hosokawa) */ + if (sio_irq_bug || COM_IRQBUG(idev)) { + if (idev->id_irq & 0xff) { + outb(IO_ICU1 + 1, ((idev->id_irq & 0xff)^0xff)); + } + if (idev->id_irq & 0xff00) { + outb(IO_ICU2 + 1, (((idev->id_irq >> 8) & 0xff)^0xff)); + } + } + #endif + #if NCARD > 0 + /* + * Functional ID 2 of PC-card suggests that the card is + * serial cards, so, these tests are nonsence (and in fact, + * many PC-cards fail these tests). I think these tests + * can be omitted when the card is PC-card, but currently, + * following XXX code only skips some tests. + * Any ideas? + * + * Tatsumi Hosokawa + */ + if (probe_pccard) { /* XXX */ + int t; + t = inb(iobase + com_iir) & IIR_IMASK; + failures[4] = !(t == IIR_TXRDY || t == IIR_NOPEND); + if (t == IIR_NOPEND) { + printf("sio%d: Warning: IIR status error.\n", + dev->id_unit); + } + } + else { + failures[4] = !((inb(iobase + com_iir) & IIR_IMASK) + == IIR_TXRDY); + } + #else /* NCARD > 0 */ failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY; + #endif /* NCARD > 0 */ DELAY(1000); /* XXX */ irqmap[2] = isa_irq_pending(); + #if NCARD > 0 + if (probe_pccard && (failures[3] || failures[5])) { /* XXX */ + printf("sio%d: Warning: irq_pending error.\n", dev->id_unit); + failures[3] = failures[5] = 0; + iperror = 1; + } + if (probe_pccard) { /* XXX */ + int t; + t = inb(iobase + com_iir) & IIR_IMASK; + failures[6] = !(t == IIR_TXRDY || t == IIR_NOPEND); + if (t == IIR_TXRDY) { + printf("sio%d: Warning: IIR status error.\n", + dev->id_unit); + } + } + else { + failures[6] = !((inb(iobase + com_iir) & IIR_IMASK) + == IIR_NOPEND); + } + #else /* NCARD > 0 */ failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; + #endif /* NCARD > 0 */ /* * Turn off all device interrupts and check that they go off properly. *************** *** 646,651 **** --- 882,896 ---- failures[7] = inb(iobase + com_ier); DELAY(1000); /* XXX */ irqmap[3] = isa_irq_pending(); + #if NCARD > 0 + if (probe_pccard && failures[8]) { /* XXX */ + if (!iperror) { + printf("sio%d: Warning: irq_pending error.\n", + dev->id_unit); + } + failures[8] = 0; + } + #endif /* NCARD > 0 */ failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; enable_intr(); *************** *** 674,679 **** --- 919,929 ---- } break; } + #ifdef NECMG + if (0 < com_power) { + necmg_com_power(com_power, 0 /* OFF */); + } + #endif /* NECMG */ return (iobase == siocniobase ? IO_COMSIZE : result); } *************** *** 756,761 **** --- 1006,1024 ---- int s; int unit; + #ifdef NECMG + if (isdp->id_unit != comconsole) { + if (&necmg_isa_comdev[isdp->id_unit] != isdp && + (isdp->id_iobase == NECMG_IO_COM1 || + isdp->id_iobase == NECMG_IO_COM3)) { + /* called from isa.c */ + dev = makedev(CDEV_MAJOR, 0); + cdevsw_add(&dev, &sio_cdevsw, NULL); + return (1); + } + } + #endif /* NECMG */ + isdp->id_ri_flags |= RI_FAST; iobase = isdp->id_iobase; unit = isdp->id_unit; *************** *** 795,800 **** --- 1058,1064 ---- com->mcr_image = inb(com->modem_ctl_port); com->line_status_port = iobase + com_lsr; com->modem_status_port = iobase + com_msr; + com->intr_ctl_port = iobase + com_ier; /* * We don't use all the flags from since they *************** *** 812,817 **** --- 1076,1083 ---- com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; com->it_in.c_lflag = TTYDEF_LFLAG; com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; + com->lt_out.c_ispeed = com->lt_out.c_ospeed = + com->lt_in.c_ispeed = com->lt_in.c_ospeed = com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; } else com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; *************** *** 829,835 **** #endif /* DSI_SOFT_MODEM */ #ifdef COM_MULTIPORT ! if (!COM_ISMULTIPORT(isdp)) #endif { u_char scr; --- 1095,1103 ---- #endif /* DSI_SOFT_MODEM */ #ifdef COM_MULTIPORT ! if (!COM_ISMULTIPORT(isdp) && !COM_IIR_TXRDYBUG(isdp)) ! #else ! if (!COM_IIR_TXRDYBUG(isdp)) #endif { u_char scr; *************** *** 849,854 **** --- 1117,1123 ---- } outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); DELAY(100); + com->st16650a = 0; switch (inb(com->int_id_port) & IIR_FIFO_MASK) { case FIFO_RX_LOW: printf(" 16450"); *************** *** 860,906 **** printf(" 16550?"); break; case FIFO_RX_HIGH: - printf(" 16550A"); if (COM_NOFIFO(isdp)) { ! printf(" fifo disabled"); } else { com->hasfifo = TRUE; ! com->tx_fifo_size = 16; #ifdef COM_ESP ! for (espp = likely_esp_ports; *espp != 0; espp++) ! if (espattach(isdp, com, *espp)) { ! com->tx_fifo_size = 1024; ! break; ! } #endif } - #if 0 - /* - * Check for the Startech ST16C650 chip. - * it has a shadow register under the com_iir, - * which can only be accessed when cfcr == 0xff - */ - { - u_char i, j; - i = inb(iobase + com_iir); - outb(iobase + com_cfcr, 0xff); - outb(iobase + com_iir, 0x0); - outb(iobase + com_cfcr, CFCR_8BITS); - j = inb(iobase + com_iir); - outb(iobase + com_iir, i); - if (i != j) { - printf(" 16550A"); - } else { - com->tx_fifo_size = 32; - printf(" 16650"); - } - if (!com->tx_fifo_size) - printf(" fifo disabled"); - } - #endif break; } #ifdef COM_ESP if (com->esp) { /* --- 1129,1165 ---- printf(" 16550?"); break; case FIFO_RX_HIGH: if (COM_NOFIFO(isdp)) { ! printf(" 16550A fifo disabled"); } else { com->hasfifo = TRUE; ! if (COM_ST16650A(isdp)) { ! com->st16650a = 1; ! com->tx_fifo_size = 32; ! printf(" ST16650A"); ! } else { ! com->tx_fifo_size = COM_FIFOSIZE(isdp); ! printf(" 16550A"); ! } ! } #ifdef COM_ESP ! for (espp = likely_esp_ports; *espp != 0; espp++) ! if (espattach(isdp, com, *espp)) { ! com->tx_fifo_size = 1024; ! break; ! } #endif + if (!com->st16650a) { + if (!com->tx_fifo_size) + com->tx_fifo_size = 16; + else + printf(" lookalike with %d bytes FIFO", + com->tx_fifo_size); } break; } + #ifdef COM_ESP if (com->esp) { /* *************** *** 940,945 **** --- 1199,1208 ---- COM_MPMASTER(isdp))->id_irq == 0; } #endif /* COM_MULTIPORT */ + if (unit == comconsole) + printf(", console"); + if ( COM_IIR_TXRDYBUG(isdp) ) + printf(" with a bogus IIR_TXRDY register"); printf("\n"); s = spltty(); *************** *** 968,973 **** --- 1231,1237 ---- unit | CALLOUT_MASK | CONTROL_LOCK_STATE, DV_CHR, UID_UUCP, GID_DIALER, 0660, "cuala%n", unit); #endif + com->id_flags = isdp->id_flags; /* Heritate id_flags for later */ return (1); } *************** *** 988,993 **** --- 1252,1278 ---- mynor = minor(dev); unit = MINOR_TO_UNIT(mynor); + #ifdef NECMG + /* + printf("unit=%d comcons=%d com_addr=%x iobase=%x\n", + unit, comconsole, com_addr(unit), necmg_isa_comdev[unit].id_iobase); + */ + if (unit != comconsole) { + struct isa_device *isdp = &necmg_isa_comdev[unit]; + if (com_addr(unit) == NULL) { + if (isdp->id_iobase == NECMG_IO_COM1) { + necmg_com_power(NECMG_COM1, 1 /* ON */) == 0 && + sioprobe(isdp) && + sioattach(isdp); + } else + if (isdp->id_iobase == NECMG_IO_COM3) { + necmg_com_power(NECMG_COM3, 1 /* ON */) == 0 && + sioprobe(isdp) && + sioattach(isdp); + } + } + } + #endif /* NECMG */ if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL) return (ENXIO); if (com->gone) *************** *** 1107,1114 **** (void) inb(com->data_port); com->prev_modem_status = com->last_modem_status = inb(com->modem_status_port); ! outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS ! | IER_EMSC); enable_intr(); /* * Handle initial DCD. Callout devices get a fake initial --- 1392,1404 ---- (void) inb(com->data_port); com->prev_modem_status = com->last_modem_status = inb(com->modem_status_port); ! if (COM_IIR_TXRDYBUG(com)) { ! outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS ! | IER_EMSC); ! } else { ! outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY ! | IER_ERLS | IER_EMSC); ! } enable_intr(); /* * Handle initial DCD. Callout devices get a fake initial *************** *** 1177,1182 **** --- 1467,1485 ---- ttyclose(tp); siosettimeout(); splx(s); + #ifdef NECMG + if (com->unit != comconsole) { + struct isa_device *isdp = &necmg_isa_comdev[com->unit]; + if (isdp->id_iobase == NECMG_IO_COM1) { + necmg_com_power(NECMG_COM1, 0 /* OFF */); + com->gone = 1; + } else + if (isdp->id_iobase == NECMG_IO_COM3) { + necmg_com_power(NECMG_COM3, 0 /* OFF */); + com->gone = 1; + } + } + #endif /* NECMG */ if (com->gone) { printf("sio%d: gone\n", com->unit); s = spltty(); *************** *** 1349,1358 **** --- 1652,1666 ---- * devices, then the edge from one may be lost because another is * on. */ + COM_LOCK(); do { possibly_more_intrs = FALSE; for (unit = 0; unit < NSIOTOT; ++unit) { com = com_addr(unit); + /* + * XXX COM_LOCK(); + * would it work here, or be counter-productive? + */ if (com != NULL && !com->gone && (inb(com->int_id_port) & IIR_IMASK) *************** *** 1360,1367 **** --- 1668,1677 ---- siointr1(com); possibly_more_intrs = TRUE; } + /* XXX COM_UNLOCK(); */ } } while (possibly_more_intrs); + COM_UNLOCK(); #endif /* COM_MULTIPORT */ } *************** *** 1373,1382 **** u_char modem_status; u_char *ioptr; u_char recv_data; ! while (TRUE) { line_status = inb(com->line_status_port); /* input event? (check first to help avoid overruns) */ while (line_status & LSR_RCV_MASK) { /* break/unnattached error bits or real input? */ --- 1683,1713 ---- u_char modem_status; u_char *ioptr; u_char recv_data; + u_char int_ident; + u_char int_ctl; + u_char int_ctl_new; + + int_ctl = inb(com->intr_ctl_port); + int_ctl_new = int_ctl; ! while (!com->gone) { line_status = inb(com->line_status_port); + #if NCARD > 0 + /* + * Some PC-cards trigger an interrupt during removal. + * Reads on a removed card return 0xff, which forces + * this interrupt handler into a loop. + * Torsten Kohler + */ + + if (line_status == 0xff) { + log(LOG_ERR, + "sio: strange line status - PC-card removed?\n"); + return; + } + #endif /* NCARD > 0 */ + /* input event? (check first to help avoid overruns) */ while (line_status & LSR_RCV_MASK) { /* break/unnattached error bits or real input? */ *************** *** 1499,1504 **** --- 1830,1838 ---- ++com->bytes_out; } com->obufq.l_head = ioptr; + if (COM_IIR_TXRDYBUG(com)) { + int_ctl_new = int_ctl | IER_ETXRDY; + } if (ioptr >= com->obufq.l_tail) { struct lbq *qp; *************** *** 1511,1516 **** --- 1845,1853 ---- com->obufq.l_next = qp; } else { /* output just completed */ + if ( COM_IIR_TXRDYBUG(com) ) { + int_ctl_new = int_ctl & ~IER_ETXRDY; + } com->state &= ~CS_BUSY; } if (!(com->state & CS_ODONE)) { *************** *** 1519,1524 **** --- 1856,1864 ---- setsofttty(); /* handle at high level ASAP */ } } + if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { + outb(com->intr_ctl_port, int_ctl_new); + } } /* finished? */ *************** *** 1710,1715 **** --- 2050,2064 ---- return (ENOTTY); } splx(s); + if (com->gone) { + printf("sio%d: gone\n", com->unit); + s = spltty(); + com_addr(com->unit) = 0; + bzero(tp,sizeof *tp); + bzero(com,sizeof *com); + free(com,M_TTYS); + splx(s); + } return (0); } *************** *** 1921,1927 **** if (cflag & CSTOPB) cfcr |= CFCR_STOPB; ! if (com->hasfifo && divisor != 0) { /* * Use a fifo trigger level low enough so that the input * latency from the fifo is less than about 16 msec and --- 2270,2276 ---- if (cflag & CSTOPB) cfcr |= CFCR_STOPB; ! if (com->hasfifo) { /* * Use a fifo trigger level low enough so that the input * latency from the fifo is less than about 16 msec and *************** *** 2007,2016 **** --- 2356,2373 ---- if (inb(iobase + com_dlbh) != dlbh) outb(iobase + com_dlbh, dlbh); } + + outb(iobase + com_cfcr, com->cfcr_image = cfcr); + if (!(tp->t_state & TS_TTSTOP)) com->state |= CS_TTGO; + if (cflag & CRTS_IFLOW) { + if (com->st16650a) { + outb(iobase + com_cfcr, 0xbf); + outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); + } com->state |= CS_RTS_IFLOW; /* * If CS_RTS_IFLOW just changed from off to on, the change *************** *** 2025,2032 **** --- 2382,2394 ---- * on here, since comstart() won't do it later. */ outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); + if (com->st16650a) { + outb(iobase + com_cfcr, 0xbf); + outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); + } } + /* * Set up state to handle output flow control. * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? *************** *** 2038,2044 **** --- 2400,2420 ---- com->state |= CS_CTS_OFLOW; if (!(com->last_modem_status & MSR_CTS)) com->state &= ~CS_ODEVREADY; + if (com->st16650a) { + outb(iobase + com_cfcr, 0xbf); + outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); + } + } else { + if (com->st16650a) { + outb(iobase + com_cfcr, 0xbf); + outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); + } } + + + outb(iobase + com_cfcr, com->cfcr_image); + + /* XXX shouldn't call functions while intrs are disabled. */ disc_optim(tp, t, com); /* *************** *** 2081,2086 **** --- 2457,2463 ---- } enable_intr(); if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { + ttwwakeup(tp); splx(s); return; } *************** *** 2150,2156 **** return; disable_intr(); if (rw & FWRITE) { - #ifdef COM_ESP_BUG_FIXED if (com->hasfifo) #ifdef COM_ESP /* XXX avoid h/w bug. */ --- 2527,2532 ---- *************** *** 2159,2165 **** /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_XMT_RST | com->fifo_image); - #endif com->obufs[0].l_queued = FALSE; com->obufs[1].l_queued = FALSE; if (com->state & CS_ODONE) --- 2535,2540 ---- *************** *** 2168,2174 **** com->tp->t_state &= ~TS_BUSY; } if (rw & FREAD) { - #ifdef COM_ESP_BUG_FIXED if (com->hasfifo) #ifdef COM_ESP /* XXX avoid h/w bug. */ --- 2543,2548 ---- *************** *** 2177,2183 **** /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_RCV_RST | com->fifo_image); - #endif com_events -= (com->iptr - com->ibuf); com->iptr = com->ibuf; } --- 2551,2556 ---- *************** *** 2366,2372 **** tp->t_state &= ~TS_CAN_BYPASS_L_RINT; /* * Prepare to reduce input latency for packet ! * discplines with a end of packet character. */ if (tp->t_line == SLIPDISC) com->hotchar = 0xc0; --- 2739,2745 ---- tp->t_state &= ~TS_CAN_BYPASS_L_RINT; /* * Prepare to reduce input latency for packet ! * discplines with a end of packet charactor. */ if (tp->t_line == SLIPDISC) com->hotchar = 0xc0; *************** *** 2409,2414 **** --- 2782,2823 ---- ; } + /* + * Read the serial port specified and try to figure out what speed + * it's currently running at. We're assuming the serial port has + * been initialized and is basicly idle. This routine is only intended + * to be run at system startup. + * + * If the value read from the serial port doesn't make sense, return 0. + */ + + static speed_t + siocngetspeed(iobase, table) + Port_t iobase; + struct speedtab *table; + { + int code; + u_char dlbh; + u_char dlbl; + u_char cfcr; + + cfcr = inb(iobase + com_cfcr); + outb(iobase + com_cfcr, CFCR_DLAB | cfcr); + + dlbl = inb(iobase + com_dlbl); + dlbh = inb(iobase + com_dlbh); + + outb(iobase + com_cfcr, cfcr); + + code = dlbh << 8 | dlbl; + + for ( ; table->sp_speed != -1; table++) + if (table->sp_code == code) + return (table->sp_speed); + + return 0; /* didn't match anything sane */ + } + static void siocnopen(sp) struct siocnstate *sp; *************** *** 2482,2502 **** siocnprobe(cp) struct consdev *cp; { ! int unit; ! /* XXX: ick */ ! unit = DEV_TO_UNIT(CONUNIT); ! siocniobase = CONADDR; ! ! /* make sure hardware exists? XXX */ ! ! /* initialize required fields */ ! cp->cn_dev = makedev(CDEV_MAJOR, unit); ! #ifdef COMCONSOLE ! cp->cn_pri = CN_REMOTE; /* Force a serial port console */ ! #else ! cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL; ! #endif } void --- 2891,2956 ---- siocnprobe(cp) struct consdev *cp; { ! speed_t boot_speed; ! u_char cfcr; ! struct isa_device *dvp; ! int s; ! struct siocnstate sp; ! ! /* ! * Find our first enabled console, if any. If it is a high-level ! * console device, then initialize it and return successfully. ! * If it is a low-level console device, then initialize it and ! * return unsuccessfully. It must be initialized in both cases ! * for early use by console drivers and debuggers. Initializing ! * the hardware is not necessary in all cases, since the i/o ! * routines initialize it on the fly, but it is necessary if ! * input might arrive while the hardware is switched back to an ! * uninitialized state. We can't handle multiple console devices ! * yet because our low-level routines don't take a device arg. ! * We trust the user to set the console flags properly so that we ! * don't need to probe. ! */ ! cp->cn_pri = CN_DEAD; ! for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) ! if (dvp->id_driver == &siodriver && dvp->id_enabled ! && COM_CONSOLE(dvp)) { ! siocniobase = dvp->id_iobase; ! s = spltty(); ! if (boothowto & RB_SERIAL) { ! boot_speed = siocngetspeed(siocniobase, ! comspeedtab); ! if (boot_speed) ! comdefaultrate = boot_speed; ! } ! /* ! * Initialize the divisor latch. We can't rely on ! * siocnopen() to do this the first time, since it ! * avoids writing to the latch if the latch appears ! * to have the correct value. Also, if we didn't ! * just read the speed from the hardware, then we ! * need to set the speed in hardware so that ! * switching it later is null. ! */ ! cfcr = inb(siocniobase + com_cfcr); ! outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); ! outb(siocniobase + com_dlbl, ! COMBRD(comdefaultrate) & 0xff); ! outb(siocniobase + com_dlbh, ! (u_int) COMBRD(comdefaultrate) >> 8); ! outb(siocniobase + com_cfcr, cfcr); ! ! siocnopen(&sp); ! splx(s); ! if (!COM_LLCONSOLE(dvp)) { ! cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); ! cp->cn_pri = COM_FORCECONSOLE(dvp) ! || boothowto & RB_SERIAL ! ? CN_REMOTE : CN_NORMAL; ! } ! break; ! } } void Index: PAO/sys/i386/isa/sioreg.h diff -c PAO/sys/i386/isa/sioreg.h:1.1.1.1 PAO/sys/i386/isa/sioreg.h:1.1.1.1.8.1 *** PAO/sys/i386/isa/sioreg.h:1.1.1.1 Thu Dec 11 22:37:04 1997 --- PAO/sys/i386/isa/sioreg.h Sun Dec 6 07:47:50 1998 *************** *** 106,111 **** --- 106,114 ---- #define MSR_DDSR 0x02 #define MSR_DCTS 0x01 + /* speed to initalize to during chip tests */ + #define SIO_TEST_SPEED 9600 + /* * WARNING: Serial console is assumed to be at COM1 address * and CONUNIT must be 0. Index: PAO/sys/i386/isa/spc.c diff -c /dev/null PAO/sys/i386/isa/spc.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:07 1998 --- PAO/sys/i386/isa/spc.c Sun Dec 6 07:47:51 1998 *************** *** 0 **** --- 1,1366 ---- + /* + * Copyright (c) 1995, 1996 Takahide Matsutsuka + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + /* + * REX-5535 (MB89352A (SPC)) SCSI Driver + * by Takahide Matsutsuka (matsu@cs.titech.ac.jp) February, 1996 + * + * Acknowledgements: Many of the algorithms used in this driver are + * inspired by the work of Tohru Kobayashi (koba@lsi.yokogawa.co.jp). + * Thanks a lot! + */ + /* + * This version work on: + * RATOC REX-5535/5535AC/5535AMC/5535X/5535XM + * + * $Id: spc.c,v 1.1.8.1 1998/12/05 22:47:51 itojun Exp $ + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + + #ifdef PC98 + #include + #else + #include + #endif + #include + #include + + #include + + #include "apm.h" + #if NAPM > 0 + #include + #endif /* NAPM > 0 */ + + /* pccard support */ + #include "card.h" + #if NCARD > 0 + #include + #include + #include + #include + #endif /* NCARD > 0 */ + + #include + + #include "spc.h" + #ifndef NSPC + #define NSPC 1 + #endif + #define SPC_HOST_ID 7 + #define NTARGETS 8 + #define NLUNS 8 + #define SPC_TIMEOUT 10000000 + + #define SPC_SET_TC(port, len) do {\ + outb((port) + SPC_TCH, (len)>>16);\ + outb((port) + SPC_TCM, (len)>>8);\ + outb((port) + SPC_TCL, (len));\ + } while(0) + #define SPC_GET_TC(port) (\ + (inb((port) + SPC_TCH)<<16)|\ + (inb((port) + SPC_TCM)<<8)|\ + inb((port) + SPC_TCL)\ + ) + + #define SQ_FLG_USEDISCON (1<<0) + #define SQ_FLG_RSNS (1<<1) /* request sense */ + + static int spc_unit = 0; + + struct spc_queue { + struct spc_queue *cq_next; + int flags; + struct scsi_xfer *xs; + u_char *data; /* data pointer */ + int datalen; /* data pointer */ + struct scsi_xfer *alt_xs; /* */ + u_char *alt_data; /* data pointer */ + int alt_datalen; /* data pointer */ + int alt_statusbyte; + }; + + typedef enum { + IN_BUSFREE = 0, + IN_SELECTION_IN_PROGRESS, + IN_CONNECTED_MO, + IN_CONNECTED, + IN_WAITDISCONNECT, + IN_WAITBUSFREE + } SPC_STATE; + + static struct spc_data { /* one of these per adapter */ + int unit; + int baseport; /* I/O base */ + SPC_STATE state; + struct scsi_link sc_link; /* each existing device */ + struct spc_queue *cq_first; /* command queue first */ + struct spc_queue *cq_last; /* command queue last */ + struct spc_queue *fq_first; /* free queue first */ + struct spc_queue *fq_last; /* free queue last */ + struct spc_queue *busy[NTARGETS][NLUNS]; + int target; /* current target */ + int lun; /* current lun */ + u_char *data; /* current data pointer */ + int datalen; /* current data pointer */ + int statusbyte; + int slot; /* information for reconfiguration */ + int alive; /* is driver alive? */ + } *spcdata[NSPC]; + + /* the below structure is so we have a default dev struct for out link struct */ static struct scsi_device spc_dev = { + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + "spc", + 0, + { 0, 0 } + }; + + static inline void + spc_free_queue(struct spc_data *spc, struct spc_queue *sq) + { + unsigned int s = splbio(); + if( !spc->fq_first ) + spc->fq_first = sq; + else + spc->fq_last->cq_next = sq; + spc->fq_last = sq; + splx(s); + } + + /* prototypes ... */ + /* called by higher level drivers */ + static int spc_probe(struct isa_device *); + static int spc_attach(struct isa_device *); + static int32_t spc_scsi_cmd(struct scsi_xfer *); + static u_int32_t spc_adapter_info(int); + static void spc_minphys(struct buf *); + /*void spcintr(int);*/ + + /* private routines */ + static void spc_done(struct spc_data *, int32_t); + static int spc_command(struct spc_data *); + static void spc_selection(struct spc_data *); + static int spc_sel_sub(struct spc_data *, struct spc_queue *, int32_t *); + static int spc_reselection(struct spc_data *, int); + static int spc_poll(struct spc_data *, struct spc_queue *); + static int spc_progtx(int, u_char *, int, int, int *); + static int spc_progrx(int, u_char *, int, int, int *); + static int spc_byte_in(int, int); + static int spc_byte_out(int, int, int); + static int spc_next_phase(int); + static int spc_pollport(int, int, int); + static struct scsi_xfer *spc_alloc_rsns(const struct scsi_xfer *); + static void spc_free_rsns(struct scsi_xfer *); + static void spc_complete(struct spc_data *); + static int spc_init(struct spc_data *); + static void spc_cleanup(struct spc_data *); + static void spc_dumpreg(int, const char *); + #ifdef SCSI_DETACH + static void spcdetach __P((struct isa_device *dev)); + #endif + + /* pccard support */ + #if NCARD > 0 + static int spc_card_intr(struct pccard_devinfo *); + static void spc_card_unload(struct pccard_devinfo *); + static int spc_card_init(struct pccard_devinfo *); + + static struct pccard_device spc_info = + { + "spc", + spc_card_init, + spc_card_unload, + spc_card_intr, + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + /* This should also include net_imask?? */ + }; + + DATA_SET(pccarddrv_set, spc_info); + + static int probing_pccard = 0; + + /* + * Initialize the device - called from Slot manager. + * if first is set, then initially check for + * the device's existence before initialising it. + * Once initialised, the device table may be set up. + */ + static int + spc_card_init(struct pccard_devinfo *devi) + { + /* + * validate unit number. + */ + static int already_spcinit; + struct spc_data *spc = spcdata[devi->pd_unit]; + + if( devi->pd_unit >= NSPC ) + return(ENODEV); + /* Make sure it isn't already initialisd. */ + if( already_spcinit == 1 ) { + if( spc_init(spc) == 0 ) + return(ENXIO); + if( spc_attach(&devi->isahd) == 0 ) + return(ENXIO); + return 0; + } + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + #if 0 + printf("probe spc\n"); + #endif + probing_pccard = 1; + if( spc_probe(&devi->isahd) == 0 ) { + probing_pccard = 0; + return(ENXIO); + } + probing_pccard = 0; + #if 0 + printf("attach spc\n"); + #endif + if( spc_attach(&devi->isahd) == 0 ) + return(ENXIO); + already_spcinit = 1; + return 0; + + /* + * XXX TODO: + * If it was already inited before, the device structure + * should be already initialised. Here we do + * reset spc, + * but I don't know whether this is the best way... + */ + if( !spc_init(spc) ) + return (ENXIO); + spc_dumpreg(spc->baseport, "resume"); + printf("spc%d: resumed\n", spc->unit); + return 0; + } + /* + * spc_card_unload - unload the driver and clear the table. + * XXX TODO: + * This is called usually when the card is ejected, but + * can be caused by the modunload of a controller driver. + * The idea is reset the driver's view of the device + * and ensure that any driver entry points such as + * read and write do not hang. + */ + static void + spc_card_unload(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + struct spc_data *spc = spcdata[unit]; + + /* + * Calling printf() in xxunload() makes hotswap operations + * unstable, so I removed all printf()'s in xxunload() except + * critical ones. + * Tatsumi Hosokawa + */ + + spc->alive = 0; + #ifdef SCSI_DETACH + spcdetach(&devi->isahd); + #endif + #if 0 + printf("spc%d: unload\n", unit); + #endif + } + /* + * spc_card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int + spc_card_intr(struct pccard_devinfo *devi) + { + spcintr(devi->pd_unit); + return 1; + } + #endif /* NCARD > 0 */ + + #define SPC_DISCONNECT /* undef if driver doesn't work well yet... */ + #undef SPC_DEBUG /* display trace data */ + + #ifdef SPC_DEBUG + #define SPC_TRACE(x) printf x; + #else + #define SPC_TRACE(x) + #endif + + struct isa_driver spcdriver = { + spc_probe, spc_attach, "spc", + }; + + struct scsi_adapter spc_switch = { + spc_scsi_cmd, + spc_minphys, + 0, + 0, + spc_adapter_info, + "spc", + { 0, 0 } + }; + + /* + * INITIALIZATION ROUTINES (probe, attach ++) + */ + + /* + * spc_probe: probe for MB89352(A) SCSI controller + * returns non-zero value if a controller is found. + */ + static int + spc_probe(struct isa_device *dvp) + { + int unit = spc_unit; + struct spc_data *spc; + + SPC_TRACE(("spc: probe\n")); + + if( (unit >= NSPC) && !dvp->id_reconfig ) { + printf("spc%d: unit number too high\n", unit); + return 0; + } + + if ((dvp->id_flags & SPC_FLAGS_PCCARD_ONLY) && !probing_pccard) + return 0; + + if( !dvp->id_reconfig ) { + /* prepare structure for the unit */ + spc = malloc(sizeof(struct spc_data), M_TEMP, M_NOWAIT); + bzero(spc, sizeof(struct spc_data)); + spc->baseport = dvp->id_iobase; + spc->fq_first = spc->fq_last = 0; + spcdata[unit] = spc; + dvp->id_unit = unit; + + if( !spc_init(spc) ) { + /* init failed, maybe scsi bus is off-lined */ + free(spc, M_TEMP); + return 0; + } + + spc_unit++; /* for the next adapter */ + printf("spc%d: REX5535 (MB89352A) PCMCIA SCSI adapter\n", unit); + } else { + /* reconfiguration time */ + spc = spcdata[dvp->id_unit]; + if( !spc_init(spc) ) + return 0; + } + + return 16; + } + + #ifdef SCSI_DETACH + static void + spcdetach(dev) + struct isa_device *dev; + { + int unit = dev->id_unit; + struct scsibus_data *scbus; + + scbus = (struct scsibus_data *)scsi_extend_get(spcdata[unit]->sc_link.scsibus); + scsi_detachdev(scbus); + } + #endif + + + static int + spc_attach(struct isa_device *dvp) + { + int unit = dvp->id_unit; + struct spc_data *spc = spcdata[unit]; + struct scsibus_data *scbus; + + SPC_TRACE(("spc%d: attach\n",unit)); + + if( dvp->id_reconfig ) + return 1; + + /* + * fill in the prototype scsi_link. + */ + spc->sc_link.adapter_unit = unit; + spc->sc_link.adapter_targ = SPC_HOST_ID; + spc->sc_link.adapter_softc = spc; + spc->sc_link.adapter = &spc_switch; + spc->sc_link.device = &spc_dev; + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if( !scbus ) return 0; + scbus->adapter_link = &spc->sc_link; + + /* + * ask the adapter what subunits are present + */ + + scsi_attachdevs(scbus); + + return 1; + } + + static u_int32_t + spc_adapter_info(int unit) + { + SPC_TRACE(("spc%d: adapter_info\n", unit)); + return 2; /* 2 outstanding requests at a time are acceptable */ + } + + static void + spc_minphys(struct buf *bp) + { + SPC_TRACE(("spc_minphys:%d\n", bp->b_bcount)); + #if 0 /* probably not needed...can it be true? */ + #define PAGESIZ 4096 + #define SPC_NSEG 2 + if( bp->b_bcount > ((SPC_NSEG - 1) * PAGESIZ) ) + bp->b_bcount = ((SPC_NSEG - 1) * PAGESIZ); + #endif + } + + /* + * DRIVER ROUTINES (scsi_cmd, selection, ++) + */ + + /* + * desirable sequence + * 1.spc_scsi_cmd: receive scsi_xfer and queueing + * 2.spcintr: called by kernel interrupt handler + * 3.proceed scsi sequence + * (1) spc_selection: starts new scsi command from queue + * (2) spc_command: proceed scsi phase + * (3) spc_reselection: reselected by target + * (4) spc_complete: if needed, do self request sense + * (5) spc_poll: if booting time, don't use interrupt + */ + /* + * spc_scsi_cmd: receive scsi command from higher level module + */ + static int32_t + spc_scsi_cmd(struct scsi_xfer *xs) + { + int unit = xs->sc_link->adapter_unit; + struct spc_data *spc = spcdata[unit]; + struct spc_queue *sq; + unsigned int s; + int32_t erc; + + SPC_TRACE(("spc%d:spc_scsi_cmd\n", unit)); + if( !spc->alive ) { + /* now card is off-lined */ + xs->error = XS_DRIVER_STUFFUP; + return (COMPLETE); + } + /* queueing command */ + if( spc->fq_first ) { + s = splbio(); + sq = spc->fq_first; + spc->fq_first = spc->fq_first->cq_next; + splx(s); + } else { + if( (sq = (struct spc_queue *) malloc(sizeof(struct spc_queue), + M_TEMP, M_NOWAIT)) == NULL ) { + /* can't malloc */ + printf("spc%d: queue full\n", spc->unit); + return (TRY_AGAIN_LATER); + } + } + + sq->xs = xs; + sq->data = xs->data; + sq->datalen = xs->datalen; + sq->cq_next = NULL; + sq->alt_xs = NULL; + #ifndef SPC_DISCONNECT + sq->flags = 0; + #else + sq->flags = SQ_FLG_USEDISCON; + #endif + + if( xs->flags & SCSI_NOMASK ) { + /* it's booting time. don't allow interrupts. */ + sq->flags &= ~SQ_FLG_USEDISCON; + erc = spc_poll(spc, sq); + spc_free_queue(spc, sq); + return erc; + } + + s = splbio(); + /* add to end of queue */ + if( spc->cq_first == NULL ) { + spc->cq_first = sq; + } else { + spc->cq_last->cq_next = sq; + } + spc->cq_last = sq; + spc_selection(spc); /* start selection */ + outb(spc->baseport + SPC_SCTL, SPC_SCTL_ENABLE); /* enable interrupt */ + splx(s); + return (SUCCESSFULLY_QUEUED); + } + + /* + * spcintr: called by kernel interrupt handler + */ + void + spcintr(int unit) + { + struct spc_data *spc = spcdata[unit]; + int port = spc->baseport; + int intr, target = 0; + + SPC_TRACE(("spc%d: spcintr\n", unit)); + intr = inb(port + SPC_INTS); /* read interrupt */ + if( intr & SPC_INTS_RESELECT ) { + target = inb(port + SPC_TEMP); + } + outb(port + SPC_INTS, intr); /* clear interrupt */ + + #if NCARD > 0 + if (intr == 0xff) { + printf("spc%d: strange status - PC-card removed?\n", + spc->unit); + return; + } + #endif /* NCARD > 0 */ + + /* HARDERR */ + if( intr & SPC_INTS_HARDERR ) { + printf("spc%d: HARDERR SERR=0x%x\n", spc->unit, inb(port + SPC_SERR)); + goto err; + } + + /* RESET */ + if( intr & SPC_INTS_RESET ) { + printf("spc%d: reset condition\n", spc->unit); + goto err; + } + + /* SERVREQ */ + if( intr & SPC_INTS_SERVREQ ) { + printf("spc%d: spurious interrupt(SERVREQ)\n", spc->unit); + goto err; + } + + /* DISCONNECT */ + if( intr & SPC_INTS_DISCONNECT ) { + if( spc->state == IN_WAITDISCONNECT ) { + /* nothing to do */ + } else if( spc->state == IN_WAITBUSFREE ) { + spc_complete(spc); + } else { + printf("spc%d: spurious interrupt(DISCONNECT) state=%d\n", + spc->unit, spc->state); + goto err; + } + spc->state = IN_BUSFREE; + } + + /* RESELECT */ + if( intr & SPC_INTS_RESELECT ) { + if( spc->state == IN_SELECTION_IN_PROGRESS ) { + outb(port + SPC_SCMD, SPC_SCMD_RESETATN); /* reset ATN */ + if( (spc->busy[spc->target][spc->lun]->flags & SQ_FLG_RSNS) == 0 ) { + spc->busy[spc->target][spc->lun] = NULL; + } + } + if( spc_reselection(spc, target) < 0 ) { + goto err; + } + if( spc_command(spc) < 0 ) { + goto err; + } + intr &= ~(SPC_INTS_COMPLETE); + } + + /* COMPLETE */ + if( intr & SPC_INTS_COMPLETE ) { + if( spc->state == IN_SELECTION_IN_PROGRESS ) { + spc->state = IN_CONNECTED_MO; + spc->cq_first = spc->cq_first->cq_next; /* delete from queue */ + if( spc_command(spc) < 0 ) { + goto err; + } + } else { + printf("spc%d: spurious interrupt(COMPLETE) state=%d\n", + spc->unit, spc->state); + goto err; + } + } + + /* TIMEOUT */ + if( intr & SPC_INTS_TIMEOUT ) { + outb(port + SPC_SCMD, SPC_SCMD_RESETATN); /* reset ATN */ + if( spc->state == IN_SELECTION_IN_PROGRESS ) { + printf("spc%d: selection timeout id=%d\n", spc->unit, spc->target); + spc->statusbyte = -1; + spc->cq_first = spc->cq_first->cq_next; /* delete from queue */ + spc_complete(spc); + } else { + printf("spc%d: spurious interrupt(TIMEOUT) state=%d\n", + spc->unit, spc->state); + goto err; + } + spc->state = IN_BUSFREE; + } + spc_selection(spc); + return; + + err: + (void) spc_init(spc); + spc_cleanup(spc); + spc->state = IN_BUSFREE; + spc_selection(spc); + return; + } + + /* + * (1) spc_selection: starts new scsi command + */ + static void + spc_selection(struct spc_data *spc) + { + struct spc_queue *sq; + int32_t erc; + + SPC_TRACE(("spc%d: spc_selection\n", spc->unit)); + + if( spc->state != IN_BUSFREE ) { + return; + } + + again: + if( (sq = spc->cq_first) != NULL ) { + spc->state = IN_SELECTION_IN_PROGRESS; + if( spc_sel_sub(spc, sq, &erc) < 0 ) { + sq->xs->flags |= ITSDONE; + sq->xs->resid = sq->xs->datalen; + sq->xs->error = erc; + scsi_done(sq->xs); + spc->cq_first = sq->cq_next; /* delete from queue */ + spc_free_queue(spc, sq); + spc->state = IN_BUSFREE; + goto again; + } + } + } + + static int + spc_sel_sub(struct spc_data *spc, struct spc_queue *sq, int32_t *erc) + { + const struct scsi_xfer *xs; + int port = spc->baseport; + int target, lun, val; + + SPC_TRACE(("spc%d: spc_sel_sub\n", spc->unit)); + + xs = sq->xs; + target = xs->sc_link->target; + lun = xs->sc_link->lun; + + if( sq->flags & SQ_FLG_RSNS ) { + /* request sense in progress */ + if( spc->busy[target][lun] != sq ) { + printf("spc%d: ??????\n", spc->unit); + } + } else { + if( spc->busy[target][lun] ) { + /* target is busy */ + printf("spc%d: target=%d, lun=%d is busy\n", spc->unit, target, lun); + *erc = XS_BUSY; + return -1; + } + } + if( xs->flags & SCSI_RESET ) { + /* command is empty, reset controller */ + printf("spc%d: reset controller by higher module\n", spc->unit); + (void) spc_init(spc); + *erc = XS_NOERROR; + return -1; + } + + spc->target = target; + spc->lun = lun; + spc->busy[target][lun] = sq; + spc->data = xs->data; + spc->datalen = xs->datalen; + spc->statusbyte = 0; + + outb(port + SPC_PCTL, 0); /* disable bus free interrupt */ + outb(port + SPC_SCMD, SPC_SCMD_SETATN); /* set ATN for IDENTIFY MSG */ + val = inb(port + SPC_BDID); /* get host id */ + val |= (1 << spc->target); /* set target id */ + outb(port + SPC_TEMP, val); /* set host id & target id */ + outb(port + SPC_TCH, 0x0f); /* set replying time */ + outb(port + SPC_TCM, 0x46); + outb(port + SPC_TCL, 0x04); /* set twait */ + outb(port + SPC_SCMD, SPC_SCMD_SELECT); /* exec selection phase! */ + *erc = XS_NOERROR; + return 0; + } + + /* + * (2) spc_command: proceed scsi phase + */ + static int + spc_command(struct spc_data *spc) + { + struct scsi_xfer *xs; + struct spc_queue *sq; + int port = spc->baseport; + int phase, xfered, r, msg; + + SPC_TRACE(("spc%d: spc_command\n", spc->unit)); + + sq = spc->busy[spc->target][spc->lun]; + xs = sq->xs; + + again0: + if( (phase = spc_next_phase(port)) < 0 ) { + return -1; + } + + switch( phase ) { + case SPC_PCTL_MSGOUT: + outb(port + SPC_SCMD, SPC_SCMD_RESETATN); /* reset ATN */ + if( spc->state == IN_CONNECTED_MO ) { + /* send identify message */ + if( sq->flags & SQ_FLG_USEDISCON ) { + msg = 0xc0 | spc->lun; + } else { + msg = 0x80 | spc->lun; + } + if( spc_byte_out(port, msg, SPC_PCTL_MSGOUT) < 0 ) { + printf("spc%d: cannot send IDENTIFY MSG\n", spc->unit); + return -1; + } + spc->state = IN_CONNECTED; + } else { + /* send No Operation message */ + if( spc_byte_out(port, 0x08, SPC_PCTL_MSGOUT) < 0 ) { + printf("spc%d: cannot send No Operation MSG\n", spc->unit); + return -1; + } + } + break; + case SPC_PCTL_MSGIN: + if( (msg = spc_byte_in(port, SPC_PCTL_MSGIN)) < 0 ) { + return -1; + } + switch( msg ) { + case SPC_MSG_SAVEDATAP: + sq->data = spc->data; /* save data pointer */ + sq->datalen = spc->datalen; /* save data pointer */ + break; + case SPC_MSG_RESTOREP: + spc->data = sq->data; /* restore pointers */ + spc->datalen = sq->datalen; /* restore pointers */ + break; + case SPC_MSG_DISCONNECT: + spc->state = IN_WAITDISCONNECT; + return 0; + case SPC_MSG_CMDCOMPLETE: + spc->state = IN_WAITBUSFREE; + return 0; + default: + printf("spc%d: invalid message 0x%x\n", spc->unit, msg); + return -1; + } + break; + case SPC_PCTL_COMMAND: + if( spc_progtx(port, (u_char *)xs->cmd, xs->cmdlen, + phase, &xfered) < 0 ) { + return -1; + } + break; + case SPC_PCTL_DATAOUT: + r = spc_progtx(port, spc->data, spc->datalen, phase, &xfered); + spc->data += xfered; + spc->datalen -= xfered; + if( r < 0 ) { + return -1; + } + break; + case SPC_PCTL_DATAIN: + r = spc_progrx(port, spc->data, spc->datalen, phase, &xfered); + spc->data += xfered; + spc->datalen -= xfered; + if( r < 0 ) { + return -1; + } + break; + case SPC_PCTL_STATUS: + if( (spc->statusbyte = spc_byte_in(port, SPC_PCTL_STATUS)) < 0 ) { + return -1; + } + spc->statusbyte &= 0x1e; + break; + default: + printf("spc%d: invalid phase 0x%x\n", spc->unit, phase); + return -1; + } + goto again0; + } + + /* + * (3) spc_reselection: reselected by target + */ + static int + spc_reselection(struct spc_data *spc, int target) + { + struct spc_queue *sq; + int port = spc->baseport; + int id, phase, val; + + SPC_TRACE(("spc%d: spc_reselection\n", spc->unit)); + + for(id = 0; id < 8; id++) { + if( (target & (1<= 8 ) { + printf("spc%d: cannot get target ID 0x%02x\n", spc->unit, target); + return -1; + } + if( (phase = spc_next_phase(port)) < 0 ) { + return -1; + } + if( phase != SPC_PCTL_MSGIN ) { + printf("spc%d: not MSGIN\n", spc->unit); + return -1; + } + if( (val = spc_byte_in(port, SPC_PCTL_MSGIN)) < 0 ) { + printf("spc%d: cannot recive IDENTIFY MSG\n", spc->unit); + return -1; + } + if( (val & 0x80) == 0 ) { + /* not identify message */ + printf("spc%d: bogus reselection\n", spc->unit); + return -1; + } + spc->target = id; + spc->lun = val & 0x07; /* get LUN */ + sq = spc->busy[id][spc->lun]; + spc->state = IN_CONNECTED; + spc->data = sq->data; /* restore data pointer */ + spc->datalen = sq->datalen; /* restore data pointer */ + return 0; + } + + /* + * (4) spc_complete: if needed, do self request sense + */ + static void + spc_complete(struct spc_data *spc) + { + struct spc_queue *sq; + + SPC_TRACE(("spc%d: spc_complete\n", spc->unit)); + + sq = spc->busy[spc->target][spc->lun]; + if( sq->flags & SQ_FLG_RSNS ) { /* request sense in progress */ + int statusbyte; + struct scsi_xfer *sxs; + + statusbyte = spc->statusbyte; + sxs = sq->xs; + sq->xs = sq->alt_xs; + sq->alt_xs = NULL; + sq->flags &= ~SQ_FLG_RSNS; + spc->data = sq->alt_data; + spc->datalen = sq->alt_datalen; + spc->statusbyte = sq->alt_statusbyte; + spc_free_rsns(sxs); + if( statusbyte == 0 ) { + spc_done(spc, XS_SENSE); + } else { + printf("spc%d: request sense failed\n", spc->unit); + spc_done(spc, XS_DRIVER_STUFFUP); + } + } else { + switch( spc->statusbyte ) { + case 0x00: + spc_done(spc, XS_NOERROR); + break; + case 0x02: + if( sq->xs->flags & SCSI_ERR_OK ) { + spc_done(spc, XS_NOERROR); + } else if( (sq->flags & SQ_FLG_RSNS) == 0 ) { + struct scsi_xfer *sxs; + sxs = spc_alloc_rsns(sq->xs); + sq->alt_xs = sq->xs; + sq->alt_data = spc->data; + sq->alt_datalen = spc->datalen; + sq->alt_statusbyte = spc->statusbyte; + sq->xs = sxs; + sq->flags |= SQ_FLG_RSNS; + /* in queue */ + sq->cq_next = NULL; + if( spc->cq_first == NULL ) { + spc->cq_first = sq; + } else { + spc->cq_last->cq_next = sq; + } + spc->cq_last = sq; + } + break; + case 0x08: + spc_done(spc, XS_BUSY); + break; + default: + printf("spc%d: unknown statusbyte 0x%x\n", + spc->unit, spc->statusbyte); + spc_done(spc, XS_DRIVER_STUFFUP); + } + } + } + + /* + * (5) spc_poll: use polling (at booting time) + */ + static int + spc_poll(struct spc_data *spc, struct spc_queue *sq) + { + struct scsi_xfer *xs; + int port = spc->baseport; + int phase, val, wait; + int32_t erc; + + SPC_TRACE(("spc%d: spc_poll\n", spc->unit)); + + xs = sq->xs; + outb(port + SPC_INTS, 0xff); /* reset interrupt */ + spc->state = IN_SELECTION_IN_PROGRESS; + if( spc_sel_sub(spc, sq, &erc) < 0 ) { + printf("spc%d: spc_poll: selection not start\n", spc->unit); + (void) spc_init(spc); + goto err; + } + + /* need to check end of selection phase ... */ + for(wait = SPC_TIMEOUT;;) { + if( (val = inb(port + SPC_INTS)) & SPC_INTS_COMPLETE ) { + /* selection success */ + outb(port + SPC_INTS, 0xff); /* reset interrupt */ + break; + } + if( val & SPC_INTS_TIMEOUT ) { + /* selection timeout */ + outb(port + SPC_SCMD, SPC_SCMD_RESETATN); /* reset ATN */ + goto err; + } + if( wait-- == 0 ) { + printf("spc%d: spc_poll: selecton not complete\n", spc->unit); + (void) spc_init(spc); + goto err; + } + } + + spc->state = IN_CONNECTED_MO; + if( spc_command(spc) < 0 ) { + (void) spc_init(spc); + goto err; + } + + /* wait for bus free */ + if( spc_pollport(port+SPC_INTS, SPC_INTS_DISCONNECT, + SPC_INTS_DISCONNECT) < 0 ) { + printf("spc%d: spc_poll: timeout at bus free\n", spc->unit); + (void) spc_init(spc); + goto err; + } + outb(port + SPC_INTS, 0xff); /* reset interrupt */ + + xs->status = spc->statusbyte; + switch (xs->status) { + case 0x00: + xs->error = XS_NOERROR; + break; + case 0x02: + if( xs->flags & SCSI_ERR_OK ) { + xs->error = XS_NOERROR; + } else if( (sq->flags & SQ_FLG_RSNS) == 0 ) { + struct scsi_xfer *sxs; + sxs = spc_alloc_rsns(xs); + sq->alt_xs = sq->xs; + sq->alt_data = spc->data; + sq->alt_datalen = spc->datalen; + sq->alt_statusbyte = spc->statusbyte; + sq->xs = sxs; + sq->flags |= SQ_FLG_RSNS; + if( spc_poll(spc, sq) != COMPLETE ) { + xs->error = XS_DRIVER_STUFFUP; + printf("spc%d: request sense failed\n", spc->unit); + } else { + xs->error = XS_SENSE; + } + sq->xs = sq->alt_xs; + sq->alt_xs = NULL; + sq->flags &= ~SQ_FLG_RSNS; + spc->data = sq->alt_data; + spc->datalen = sq->alt_datalen; + spc->statusbyte = sq->alt_statusbyte; + spc_free_rsns(sxs); + } else { + return (HAD_ERROR); + } + break; + case 0x08: + xs->error = XS_BUSY; + break; + default: + printf("spc%d: unknown statusbyte 0x%x\n", spc->unit, xs->status); + xs->error = XS_DRIVER_STUFFUP; + } + xs->flags |= ITSDONE; + xs->resid = spc->datalen; + spc->state = IN_BUSFREE; + if( (sq->flags & SQ_FLG_RSNS) == 0 ) { + spc->busy[spc->target][spc->lun] = NULL; + } + return (COMPLETE); + err: + outb(port + SPC_INTS, 0xff); /* reset interrupt */ + xs->error = XS_TIMEOUT; + xs->flags |= ITSDONE; + xs->resid = spc->datalen; + spc->state = IN_BUSFREE; + if( (sq->flags & SQ_FLG_RSNS) == 0 ) { + spc->busy[spc->target][spc->lun] = NULL; + } + return (HAD_ERROR); + } + + /* + * MISC FUNCTIONS + */ + static struct scsi_xfer + *spc_alloc_rsns(const struct scsi_xfer *xs) + { + struct scsi_xfer *sxs; + struct scsi_sense *scmd; + + if( (sxs = malloc(sizeof(struct scsi_xfer), M_TEMP, M_NOWAIT)) == NULL ) { + return NULL; + } + if( (scmd = malloc(sizeof(struct scsi_sense), M_TEMP, M_NOWAIT)) == NULL ) { + free(sxs, M_TEMP); + return NULL; + } + bzero(sxs, sizeof(struct scsi_xfer)); + bzero(scmd, sizeof(struct scsi_sense)); + scmd->op_code = REQUEST_SENSE; + scmd->byte2 = (xs->sc_link->lun << 5) & 0xe0; + scmd->length = sizeof(struct scsi_sense_data); + sxs->flags = SCSI_DATA_IN; + sxs->cmd = (void *)scmd; + sxs->cmdlen = sizeof(struct scsi_sense); + sxs->data = (u_char *)&xs->sense; + sxs->datalen = sizeof(struct scsi_sense_data); + sxs->timeout = xs->timeout; + sxs->sc_link = xs->sc_link; + return sxs; + } + + static void + spc_free_rsns(struct scsi_xfer *sxs) + { + free(sxs->cmd, M_TEMP); + free(sxs, M_TEMP); + } + + static void + spc_dumpreg(int port, const char *p) + { + printf("spc: %s SSTS=0x%x INTS=0x%x PSNS=0x%x PCTL=0x%x\n", + p, + inb(port + SPC_SSTS), + inb(port + SPC_INTS), + inb(port + SPC_PSNS), + inb(port + SPC_PCTL)); + } + + static int + spc_pollport(int port, int mask, int ptn) + { + int wait, val; + + for(wait = SPC_TIMEOUT; wait > 0; wait--) { + if( ((val = inb(port)) & mask) == ptn ) { + return val; + } + } + return -1; + } + + static int + spc_next_phase(int port) + { + int psns; + + if( (psns = spc_pollport(port+SPC_PSNS, SPC_PSNS_REQ, SPC_PSNS_REQ)) < 0 ) { + printf("spc: spc_next_phase: REQ not assert\n"); + return -1; + } + return psns & SPC_PSNS_PHASE; + } + + static void + spc_done(struct spc_data *spc, int32_t xserror) + { + struct spc_queue *sq; + + sq = spc->busy[spc->target][spc->lun]; + spc->busy[spc->target][spc->lun] = NULL; + sq->xs->flags |= ITSDONE; + sq->xs->resid = spc->datalen; + sq->xs->status = spc->statusbyte; + sq->xs->error = xserror; + if( sq->xs->resid ) { /* XXX */ + printf("spc_done: xs %d resid %d\n", sq->xs->datalen, sq->xs->resid); + } + scsi_done(sq->xs); + spc_free_queue(spc, sq); + } + + static int + spc_progtx(int port, u_char *data, int datalen, int phase, int *xfered) + { + long wait; + int n, ssts, datalenorg; + + datalenorg = datalen; + outb(port + SPC_PCTL, phase); + SPC_SET_TC(port, datalen); /* transfer byte counter set */ + outb(port + SPC_SCMD, SPC_SCMD_PROGTX); /* programed transfer */ + + if( spc_pollport(port + SPC_SSTS, 0xf0, 0xb0) < 0 ) { + spc_dumpreg(port, "spc_progtx"); + *xfered = 0; + return -1; + } + + if( (inb(port + SPC_SSTS) & SPC_SSTS_DREMPTY) == 0 ) { /* XXX */ + spc_dumpreg(port, "AA spc_progtx: not empty"); + } + + for(;;) { + for(wait = SPC_TIMEOUT;;) { + if( ((ssts = inb(port + SPC_SSTS)) & SPC_SSTS_BUSY) == 0) { + goto doneWRITE; + } + if( (ssts & 3) == SPC_SSTS_DREMPTY ) { + break; + } + if( wait-- == 0 ) { + *xfered = datalenorg - SPC_GET_TC(port); + spc_dumpreg(port, "spc_progtx: timeout"); + return -1; + } + } + if( datalen > 0 ) { + if( datalen >= 8 ) { + n = 8; + } else { + n = datalen; + } + outsb(port + SPC_DREG, data, n); + data += n; + datalen -= n; + } + } + doneWRITE: + *xfered = datalenorg - SPC_GET_TC(port); + outb(port + SPC_INTS, SPC_INTS_COMPLETE|SPC_INTS_SERVREQ); + return 0; + } + + static int + spc_progrx(int port, u_char *data, int datalen, int phase, int *xfered) + { + int datalenorg, ssts, wait; + + datalenorg = datalen; + outb(port + SPC_PCTL, phase); + SPC_SET_TC(port, datalen); /* transfer byte counter set */ + outb(port + SPC_SCMD, SPC_SCMD_PROGRX); /* programed transfer */ + + if( spc_pollport(port+SPC_SSTS, 0xd0, 0x90) < 0 ) { + spc_dumpreg(port, "spc_progrx"); + *xfered = 0; + return -1; + } + + while(1) { + for(wait = SPC_TIMEOUT;;) { + if( ((ssts = inb(port + SPC_SSTS)) & SPC_SSTS_DREMPTY) == 0 ) { + break; + } + if( (ssts & SPC_SSTS_BUSY) == 0) { + goto doneREAD; + } + if( wait-- == 0 ) { + spc_dumpreg(port, "spc_progrx: timeout"); + *xfered = datalenorg - datalen; + return -1; + } + } + if( datalen > 0 ) { + *data++ = inb(port + SPC_DREG); + datalen--; + } else { + inb(port + SPC_DREG); /* dummy read XXX */ + } + } + doneREAD: + if( (inb(port + SPC_SSTS) & SPC_SSTS_DREMPTY) == 0 ) { /* XXX */ + spc_dumpreg(port, "spc_progrx: not empty"); + } + *xfered = datalenorg - datalen; + outb(port + SPC_INTS, SPC_INTS_COMPLETE|SPC_INTS_SERVREQ); + return 0; + } + + static int + spc_byte_in(int port, int phase) + { + int retval; + + outb(port + SPC_PCTL, phase); + outb(port + SPC_SCMD, SPC_SCMD_SETACK); + if( spc_pollport(port+SPC_PSNS, SPC_PSNS_REQ, 0) < 0 ) { + spc_dumpreg(port, "spc_byte_in"); + return -1; + } + retval = inb(port + SPC_TEMP); /* read */ + outb(port + SPC_SCMD, SPC_SCMD_RESETACK); + return retval; + } + + static int + spc_byte_out(int port, int data, int phase) + { + outb(port + SPC_PCTL, phase); + outb(port + SPC_TEMP, data); /* write */ + outb(port + SPC_SCMD, SPC_SCMD_SETACK); + if( spc_pollport(port+SPC_PSNS, SPC_PSNS_REQ, 0) < 0 ) { + spc_dumpreg(port, "spc_byte_out"); + return -1; + } + outb(port + SPC_SCMD, SPC_SCMD_RESETACK); + return 0; + } + + static int + spc_init(struct spc_data *spc) + { + int port = spc->baseport; + long count = SPC_TIMEOUT; + + outb(port + SPC_SCTL, 0x9a); /* SPC software reset */ + outb(port + SPC_BDID, SPC_HOST_ID); /* set initiator id */ + outb(port + SPC_SCMD, 0); + outb(port + SPC_PCTL, 0); + outb(port + SPC_TEMP, 0); + outb(port + SPC_TCH , 0); + outb(port + SPC_TCM , 0); + outb(port + SPC_TCL , 0); + outb(port + SPC_PSNS, 0); + DELAY(100000); /* wait 100ms */ + outb(port + SPC_SCTL, SPC_SCTL_DISABLE); /* clear SPC reset */ + outb(port + SPC_SCMD, SPC_SCMD_RESET); /* RESET SCSI bus */ + DELAY(100000); /* wait 100ms */ + outb(port + SPC_SCMD, 0); /* RESET SCSI bus */ + DELAY(5000000); /* wait 5s */ + outb(port + SPC_SCMD, SPC_SCMD_BUSRELEASE); + + /* confirm bus release ... */ + while (inb(port + SPC_PSNS) && count) count--; + if( !count ) { + printf("spc%d: init failed, driver disabled\n", spc->unit); + spc->alive = 0; + return 0; + } + spc->alive = 1; + return 1; + } + + static void + spc_cleanup(struct spc_data *spc) + { + int id, lun; + struct spc_queue *sq; + struct scsi_xfer *sxs; + + printf("spc%d: cleanup current id=%d current lun=%d state=%d\n", + spc->unit, spc->target, spc->lun, spc->state); + for(id = 0; id < NTARGETS; id++) { + for(lun = 0; lun < NLUNS; lun++) { + if( (sq = spc->busy[id][lun]) == NULL ) { + continue; + } + printf("spc%d: cleanup id=%d lun=%d\n", spc->unit, id, lun); + if( sq->flags & SQ_FLG_RSNS ) { + sxs = sq->xs; + if( sq->alt_xs == NULL ) { + continue; + } + sq->xs = sq->alt_xs; + if( sxs ) { + spc_free_rsns(sxs); + } + } + sq->xs->flags |= ITSDONE; + sq->xs->error = XS_TIMEOUT; + scsi_done(sq->xs); + spc_free_queue(spc, sq); + spc->busy[id][lun] = NULL; + } + } + } Index: PAO/sys/i386/isa/spc.h diff -c /dev/null PAO/sys/i386/isa/spc.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:07 1998 --- PAO/sys/i386/isa/spc.h Sun Dec 6 07:47:53 1998 *************** *** 0 **** --- 1,138 ---- + /* + * Copyright (c) 1995 Takahide Matsutsuka + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + /* + * Header file for REX-5535 (MB89352A (SPC)) SCSI Driver + * by Takahide Matsutsuka (matsu@cs.titech.ac.jp) February, 1996 + */ + /* + * $Id: spc.h,v 1.1.8.1 1998/12/05 22:47:53 itojun Exp $ + */ + + /* + * config flags + */ + #define SPC_FLAGS_PCCARD_ONLY 0x01 + + /* + * SPC I/O port address + */ + #define SPC_BDID 0x00 + #define SPC_SCTL 0x01 + #define SPC_SCMD 0x02 + #define SPC_TMOD 0x03 + #define SPC_INTS 0x04 + #define SPC_PSNS 0x05 + #define SPC_SSTS 0x06 + #define SPC_SERR 0x07 + #define SPC_PCTL 0x08 + #define SPC_MBC 0x09 + #define SPC_DREG 0x0a + #define SPC_TEMP 0x0b + #define SPC_TCH 0x0c + #define SPC_TCM 0x0d + #define SPC_TCL 0x0e + + /* + * SPC_SCTL spc control + */ + #define SPC_SCTL_ENABLE 0x1b + #define SPC_SCTL_DISABLE 0x18 + + /* + * SPC_SCMD command + */ + #define SPC_SCMD_BUSRELEASE 0x00 + #define SPC_SCMD_RESET 0x10 + #define SPC_SCMD_SELECT 0x20 + #define SPC_SCMD_RESETATN 0x40 + #define SPC_SCMD_SETATN 0x60 + #define SPC_SCMD_TRANSFER 0x80 + #define SPC_SCMD_TRANSPAUSE 0xa0 + #define SPC_SCMD_RESETACK 0xc0 + #define SPC_SCMD_SETACK 0xe0 + + #define SPC_SCMD_PROGTX 0x8c + #define SPC_SCMD_PROGRX 0x84 + + /* + * SPC_INTS interrupt sense + */ + #define SPC_INTS_SELECT 0x80 + #define SPC_INTS_RESELECT 0x40 + #define SPC_INTS_DISCONNECT 0x20 + #define SPC_INTS_COMPLETE 0x10 + #define SPC_INTS_SERVREQ 0x08 + #define SPC_INTS_TIMEOUT 0x04 + #define SPC_INTS_HARDERR 0x02 + #define SPC_INTS_RESET 0x01 + + /* + * SPC_PSNS phase sense + */ + #define SPC_PSNS_REQ 0x80 + #define SPC_PSNS_ACK 0x40 + #define SPC_PSNS_ATN 0x20 + #define SPC_PSNS_SEL 0x10 + #define SPC_PSNS_BSY 0x08 + #define SPC_PSNS_MSG 0x04 + #define SPC_PSNS_CD 0x02 + #define SPC_PSNS_IO 0x01 + + #define SPC_PSNS_PHASE 0x07 + + /* + * SPC_SSTS spc status + */ + #define SPC_SSTS_INIT 0x80 + #define SPC_SSTS_TARG 0x40 + #define SPC_SSTS_BUSY 0x20 + #define SPC_SSTS_XFER 0x10 + #define SPC_SSTS_SCSIRST 0x08 + #define SPC_SSTS_TCZERO 0x04 + #define SPC_SSTS_DRFULL 0x02 + #define SPC_SSTS_DREMPTY 0x01 + + /* + * SPC_PCTL phase control + */ + #define SPC_PCTL_MSG 0x04 + #define SPC_PCTL_CD 0x02 + #define SPC_PCTL_IO 0x01 + + #define SPC_PCTL_DATAOUT 0x00 + #define SPC_PCTL_DATAIN 0x01 + #define SPC_PCTL_COMMAND 0x02 + #define SPC_PCTL_STATUS 0x03 + #define SPC_PCTL_MSGOUT 0x06 + #define SPC_PCTL_MSGIN 0x07 + + /* + * others + */ + #define SPC_MSG_CMDCOMPLETE 0x00 + #define SPC_MSG_SAVEDATAP 0x02 + #define SPC_MSG_RESTOREP 0x03 + #define SPC_MSG_DISCONNECT 0x04 Index: PAO/sys/i386/isa/syscons.c diff -c PAO/sys/i386/isa/syscons.c:1.1.1.4 PAO/sys/i386/isa/syscons.c:1.1.1.4.2.1 *** PAO/sys/i386/isa/syscons.c:1.1.1.4 Sat Dec 5 05:38:14 1998 --- PAO/sys/i386/isa/syscons.c Sun Dec 6 07:47:55 1998 *************** *** 72,77 **** --- 72,81 ---- #include #include #include + #ifdef NECMG + #include + #include + #endif #if !defined(MAXCONS) #define MAXCONS 16 *************** *** 266,272 **** --- 270,278 ---- static int history_up_line(scr_stat *scp); static int history_down_line(scr_stat *scp); static int mask2attr(struct term_stat *term); + #ifndef NECMG static void set_keyboard(int command, int data); + #endif /* !NECMG */ static void update_leds(int which); static void set_vgaregs(char *modetable); static void read_vgaregs(char *buf); *************** *** 318,323 **** --- 324,335 ---- scioctl, nullstop, noreset, scdevtotty, ttselect, scmmap, nostrategy, "sc", NULL, -1 }; + #ifdef NECMG + #ifdef NECMG_ZOOMCONS + static int necmg_zoomcons = 0; + #endif + #endif + /* * These functions need to be before calls to them so they can be inlined. */ *************** *** 369,380 **** --- 381,414 ---- } } *ptr = cursor_image; + #ifdef NECMG_DEBUG + printf("draw cursor_image=%04x, pos=%d(%d,%d)\n", + *ptr, scp->cursor_pos - scp->scr_buf, + (scp->cursor_pos - scp->scr_buf)%scp->xsize, + (scp->cursor_pos - scp->scr_buf)/scp->xsize); + #endif + #ifdef NECMG + necmg_cons_update(scp->xsize, scp->ysize, Crtat, + (scp->cursor_pos - scp->scr_buf), + (scp->cursor_pos - scp->scr_buf)); + #endif } static __inline void remove_cursor_image(scr_stat *scp) { *(Crtat + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder; + #ifdef NECMG_DEBUG + printf("erase cursor_image=%04x, pos=%d(%d,%d)\n", + scp->cursor_saveunder, scp->cursor_oldpos - scp->scr_buf, + (scp->cursor_oldpos - scp->scr_buf)%scp->xsize, + (scp->cursor_oldpos - scp->scr_buf)/scp->xsize); + #endif + #ifdef NECMG + necmg_cons_update(scp->xsize, scp->ysize, Crtat, + (scp->cursor_oldpos - scp->scr_buf), + (scp->cursor_oldpos - scp->scr_buf)); + #endif } static __inline void *************** *** 426,431 **** --- 460,482 ---- if (init_done != COLD) return (Crtat != 0); + #ifdef NECMG + { + static u_short dummy[COL*ROW+1]; + Crtat = dummy; + } + crtc_type = KD_NECMG; + crtc_addr = 0; + #ifdef NECMG_DEBUG + printf("necmg_fontrom_base = %x\n", necmg_fontrom_base); + /* + printf("necmg_fontrom_base = %x (physaddr = %x)\n", + necmg_fontrom_base, vtophys(necmg_fontrom_base)); + */ + #endif /* NECMG_DEBUG */ + return TRUE; + #endif /* NECMG */ + /* * Finish defaulting crtc variables for a mono screen. Crtat is a * bogus common variable so that it can be shared with pcvt, so it *************** *** 517,522 **** --- 568,576 ---- return ((flags & DETECT_KBD) ? FALSE : TRUE); } + #ifdef NECMG + return TRUE; + #else /* NECMG */ /* discard anything left after UserConfig */ empty_both_buffers(sc_kbdc, 10); *************** *** 657,670 **** (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); kbdc_lock(sc_kbdc, FALSE); return FALSE; } #if NAPM > 0 static int scresume(void *dummy) { ! shfts = ctls = alts = agrs = metas = accents = 0; ! return 0; } #endif --- 711,735 ---- (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); kbdc_lock(sc_kbdc, FALSE); return FALSE; + #endif /* ! NECMG */ } #if NAPM > 0 static int scresume(void *dummy) { ! shfts = ctls = alts = agrs = metas = accents = 0; ! ! #ifdef SYSCONS_VTY_RESUME ! wakeup((caddr_t)&cur_console->smode); ! if (cur_console->proc && (cur_console->proc != pfind(cur_console->pid))) ! cur_console->smode.mode = VT_AUTO; ! if(cur_console->smode.mode == VT_PROCESS) { ! cur_console->status |= SWITCH_WAIT_ACQ; ! psignal(cur_console->proc, cur_console->smode.acqsig); ! } ! #endif /* SYSCONS_VTY_RESUME */ ! return 0; } #endif *************** *** 759,764 **** --- 824,844 ---- case KD_CGA: printf("CGA"); break; + #ifdef NECMG + case KD_NECMG: + if (necmg_fontrom_base == 0) { + necmg_fontrom_base = pmap_mapdev(0x1400000, 0x200000); + #ifdef NECMG_DEBUG + printf("necmg_fontrom_base = %x (physaddr = %x)\n", + necmg_fontrom_base, vtophys(necmg_fontrom_base)); + #endif + } + printf("NEC Mobile Gear %c%c%c%c%c%c %c%c%c%c%c%c%c%c%c%c", + /* NIHONGO KONSO-RU in EUC kanji code */ + 0xc6, 0xfc, 0xcb, 0xdc, 0xb8, 0xec, + 0xa5, 0xb3, 0xa5, 0xf3, 0xa5, 0xbd, 0xa1, 0xbc, 0xa5, 0xeb); + break; + #endif /* NECMG */ case KD_MONO: case KD_HERCULES: default: *************** *** 1903,1914 **** --- 1983,1996 ---- *data = scp->status & LOCK_KEY_MASK; return 0; + #ifndef NECMG case KDSETRAD: /* set keyboard repeat & delay rates */ if (*data & 0x80) return EINVAL; if (sc_kbdc != NULL) set_keyboard(KBDC_SET_TYPEMATIC, *data); return 0; + #endif /* NECMG */ case KDSKBMODE: /* set keyboard mode */ switch (*data) { *************** *** 2349,2354 **** --- 2431,2454 ---- } scp = cur_console; + #ifdef NECMG + #ifdef NECMG_ZOOMCONS + { + static int ticcount = 0; + static int prevcurpos = -1; + if (necmg_zoomcons && necmg_cons_get_zoompos() != scp->ypos) { + if (prevcurpos == scp->ypos) { + if (5 /* 0.5sec */ <= ++ticcount) { + necmg_cons_set_zoompos(scp->xsize, scp->ysize, Crtat, scp->ypos); + } + } else { + ticcount = 0; + prevcurpos = scp->ypos; + } + } + } + #endif + #endif if (scrn_blanked <= 0) scrn_update(scp, TRUE); *************** *** 2368,2373 **** --- 2468,2477 ---- if (scp->start <= scp->end) { sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, (1 + scp->end - scp->start) * sizeof(u_short)); + #ifdef NECMG + necmg_cons_update(scp->xsize, scp->ysize, + Crtat, scp->start, scp->end); + #endif } /* we are not to show the cursor and the mouse pointer... */ *************** *** 2558,2563 **** --- 2662,2675 ---- exchange_scr(void) { move_crsr(old_scp, old_scp->xpos, old_scp->ypos); + #ifdef NECMG + /* + * We don't know how to get nor set keyboard NUM lock status. + * So all virtual consoles have same NLKED bit. + */ + new_scp->status = + (new_scp->status & ~NLKED) | (cur_console->status & NLKED); + #endif cur_console = new_scp; if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){ if (crtc_vga) *************** *** 3256,3261 **** --- 3368,3377 ---- return; init_done = WARM; + #ifdef NECMG + hw_cursor = 0; + necmg_cons_clear(); + #else /* NECMG */ /* * Ensure a zero start address. This is mainly to recover after * switching from pcvt using userconfig(). The registers are w/o *************** *** 3285,3290 **** --- 3401,3407 ---- outb(crtc_addr + 1, 0xff); outb(crtc_addr, 15); outb(crtc_addr + 1, 0xff); + #endif /* set up the first console */ current_default = &user_default; *************** *** 3477,3482 **** --- 3594,3603 ---- scp->mode = M_C80x25; scp->font_size = 14; break; + case KD_NECMG: + scp->mode = M_B80x25; + scp->font_size = 8; + break; case KD_MONO: case KD_HERCULES: default: *************** *** 3613,3622 **** --- 3734,3776 ---- return scancode; } + #ifdef NECMG + #ifdef NECMG_ZOOMCONS + if (scancode == 0x3b /* AP KIRIKAE */) { + if (necmg_zoomcons) { + necmg_zoomcons = 0; + necmg_cons_set_zoompos(cur_console->xsize, cur_console->ysize, + Crtat, -1); + } else { + necmg_zoomcons = 1; + } + update_leds(cur_console->status); + return (NOKEY); + } + #endif + #endif + keycode = scancode & 0x7F; switch (esc_flag) { case 0x00: /* normal scancode */ switch(scancode) { + #ifdef NECMG + case 0x1a: /* '@~' */ + if (cur_console->status & NLKED) { + keycode = 0x5e; + } + break; + case 0x28: /* ':*' */ + if (cur_console->status & NLKED) { + keycode = 0x37; + } + break; + case 0x33: /* ',<' */ + if (cur_console->status & NLKED) { + keycode = 0x63; + } + break; + #endif case 0xB8: /* left alt (compose key) */ if (compose) { compose = 0; *************** *** 3647,3652 **** --- 3801,3811 ---- break; case 0x1D: /* right ctrl key */ keycode = 0x5A; + #ifdef NECMG + if (cur_console->status & NLKED) { + keycode = 0x59; + } + #endif break; case 0x35: /* keypad divide key */ keycode = 0x5B; *************** *** 4100,4108 **** --- 4259,4278 ---- int scmmap(dev_t dev, vm_offset_t offset, int nprot) { + #ifdef NECMG + if (offset < 0x10000) { + return i386_btop(vtophys(NECMG_FRAMEBUFFER + offset)); + } + offset -= 0x10000; + if (offset < 0x200000) { + return i386_btop(vtophys(necmg_fontrom_base + offset)); + } + return -1; + #else /* NECMG */ if (offset > 0x20000 - PAGE_SIZE) return -1; return i386_btop((VIDEOMEM + offset)); + #endif /* !NECMG */ } /* *************** *** 4134,4139 **** --- 4304,4310 ---- return attr; } + #ifndef NECMG static void set_keyboard(int command, int data) { *************** *** 4185,4194 **** --- 4356,4379 ---- #endif kbdc_lock(sc_kbdc, FALSE); } + #endif /* !NECMG */ static void update_leds(int which) { + #ifdef NECMG + int pos = 75; + #ifdef NECMG_ZOOMCONS + necmg_draw_icon(pos-- * 2, 0, necmg_icon8x8[NECMG_ICON8x8_ZOOM], 2, 8, + NECMG_WHITE, necmg_zoomcons ? NECMG_BLACK : NECMG_LIGHTGRAY); + #endif + necmg_draw_icon(pos-- * 2, 0, necmg_icon8x8[NECMG_ICON8x8_SCRL], 2, 8, + NECMG_WHITE, (which&SLKED) ? NECMG_BLACK : NECMG_LIGHTGRAY); + necmg_draw_icon(pos-- * 2, 0, necmg_icon8x8[NECMG_ICON8x8_CAPS], 2, 8, + NECMG_WHITE, (which & CLKED) ? NECMG_BLACK : NECMG_LIGHTGRAY); + necmg_draw_icon(pos-- * 2, 0, necmg_icon8x8[NECMG_ICON8x8_NUM], 2, 8, + NECMG_WHITE, (which & NLKED) ? NECMG_BLACK : NECMG_LIGHTGRAY); + #else static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; /* replace CAPS led with ALTGR led for ALTGR keyboards */ *************** *** 4200,4205 **** --- 4385,4391 ---- } set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); + #endif /* ! NECMG */ } void Index: PAO/sys/i386/isa/wcd.c diff -c PAO/sys/i386/isa/wcd.c:1.1.1.3 PAO/sys/i386/isa/wcd.c:1.1.1.3.2.1 *** PAO/sys/i386/isa/wcd.c:1.1.1.3 Sat Dec 5 05:38:18 1998 --- PAO/sys/i386/isa/wcd.c Sun Dec 6 07:47:57 1998 *************** *** 63,68 **** --- 63,74 ---- static #endif int wcdattach(struct atapi*, int, struct atapi_params*, int); + #ifdef ATAPI_DETACH + #ifndef ATAPI_STATIC + static + #endif + int wcddetach(struct atapi*, int, struct atapi_params*, int); + #endif /* ATAPI_DETACH */ #define NUNIT (NWDC*2) /* Max. number of devices */ #define UNIT(d) ((minor(d) >> 3) & 3) /* Unit part of minor device number */ *************** *** 235,241 **** --- 241,251 ---- }; struct wcd *wcdtab[NUNIT]; /* Drive info by unit number */ + #ifndef ATAPI_DETACH static int wcdnlun = 0; /* Number of configured drives */ + #else /* ATAPI_DETACH */ + static int wcd_unit_use = 0; /* Number of configured drives */ + #endif /* ATAPI_DETACH */ static void wcd_start (struct wcd *t); static void wcd_done (struct wcd *t, struct buf *bp, int resid, *************** *** 274,283 **** --- 284,304 ---- struct atapires result; int lun; + #ifndef ATAPI_DETACH if (wcdnlun >= NUNIT) { printf ("wcd: too many units\n"); return (0); } + #else /* ATAPI_DETACH */ + for (lun=0; lun < NUNIT; lun++) { + if (!(wcd_unit_use & (1 << lun))) + break; + } + if (lun >= NUNIT) { + printf ("wcd: too many units\n"); + return (0); + } + #endif /* ATAPI_DETACH */ if (!atapi_request_immediate) { printf("wcd: configuration error, ATAPI core code not present!\n"); printf("wcd: check `options ATAPI_STATIC' in your kernel config file!\n"); *************** *** 288,299 **** --- 309,329 ---- printf ("wcd: out of memory\n"); return (0); } + #ifndef ATAPI_DETACH wcdtab[wcdnlun] = t; + #else /* ATAPI_DETACH */ + wcdtab[lun] = t; + #endif /* ATAPI_DETACH */ bzero (t, sizeof (struct wcd)); bufq_init(&t->buf_queue); t->ata = ata; t->unit = unit; + #ifndef ATAPI_DETACH lun = t->lun = wcdnlun++; + #else /* ATAPI_DETACH */ + t->lun = lun; + wcd_unit_use |= (1 << lun); + #endif /* ATAPI_DETACH */ t->param = ap; t->flags = F_MEDIA_CHANGED; t->starting_lba = 0; *************** *** 349,354 **** --- 379,422 ---- return (1); } + #ifdef ATAPI_DETACH + #ifndef ATAPI_STATIC + static + #endif + int + wcddetach (struct atapi *ata, int unit, struct atapi_params *ap, int debug) + { + struct wcd **t; + int lun; + + for (lun=0; lun < NUNIT; lun++) { + if ((wcd_unit_use & (1 << lun))) { + t = wcdtab + lun; + if ((*t)->ata->port == ata->port && + (*t)->ata->ctrlr == ata->ctrlr && + (*t)->unit == unit) + break; + } + } + if (lun >= NUNIT) { + printf ("wcd: not found unit\n"); + return (0); + } + + t = wcdtab + lun; + if (((*t)->flags & F_BOPEN) || (*t)->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + (*t)->ata->attached[(*t)->unit] = 0; + free (*t, M_TEMP); + wcdtab[lun] = NULL; + + wcd_unit_use &= ~(1 << lun); + + return 0; + } + #endif /* ATAPI_DETACH */ + void wcd_describe (struct wcd *t) { char *m; *************** *** 416,423 **** --- 484,496 ---- /* Check that the device number is legal * and the ATAPI driver is loaded. */ + #ifndef ATAPI_DETACH if (lun >= wcdnlun || ! atapi_request_immediate) return (ENXIO); + #else /* ATAPI_DETACH */ + if (!(wcd_unit_use & (1 << lun)) || ! atapi_request_immediate) + return (ENXIO); + #endif /* ATAPI_DETACH */ t = wcdtab[lun]; /* On the first open, read the table of contents. */ *************** *** 1160,1165 **** --- 1233,1239 ---- { struct wcd **t; + #ifndef ATAPI_DETACH for (t=wcdtab; tflags & F_BOPEN) || (*t)->refcnt) /* The device is opened, cannot unload the driver. */ *************** *** 1169,1174 **** --- 1243,1264 ---- free (*t, M_TEMP); } wcdnlun = 0; + #else /* ATAPI_DETACH */ + for (int lun=0; lun < NUNIT; ++lun) + if (wcd_unit_use & (1 << lun)) { + t = wcdtab + lun; + if (((*t)->flags & F_BOPEN) || (*t)->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + } + for (int lun=0; lun < NUNIT; ++lun) + if (wcd_unit_use & (1 << lun)) { + t = wcdtab + lun; + (*t)->ata->attached[(*t)->unit] = 0; + free (*t, M_TEMP); + } + wcd_unit_use = 0; + #endif /* ATAPI_DETACH */ bzero (wcdtab, sizeof(wcdtab)); return 0; } Index: PAO/sys/i386/isa/wd.c diff -c PAO/sys/i386/isa/wd.c:1.1.1.4 PAO/sys/i386/isa/wd.c:1.1.1.4.2.1 *** PAO/sys/i386/isa/wd.c:1.1.1.4 Sat Dec 5 05:38:19 1998 --- PAO/sys/i386/isa/wd.c Sun Dec 6 07:47:59 1998 *************** *** 66,71 **** --- 66,73 ---- #if NWDC > 0 + #include "card.h" /* PC-card Flash/Type3 ATA support */ + #include #include #include *************** *** 90,95 **** --- 92,98 ---- #include #include #include + #include #ifdef ATAPI *************** *** 110,115 **** --- 113,123 ---- /* can't handle that in all cases */ #define WDOPT_32BIT 0x8000 #define WDOPT_SLEEPHACK 0x4000 + /* following two options are used for PC-card IDE/ATAPI devices */ + #define WDOPT_PACKED 0x2000 + #define WDOPT_BROKEN_SIGNATURE 0x1000 + + #define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8) #define WDOPT_MULTIMASK 0x00ff *************** *** 179,184 **** --- 187,195 ---- int dk_currentiosize; /* current io size */ struct diskgeom dk_dd; /* device configuration data */ struct diskslices *dk_slices; /* virtual drives */ + int dk_altsts; + int dk_ctlr; + int dk_digin; }; #define WD_COUNT_RETRIES *************** *** 224,229 **** --- 235,241 ---- static timeout_t wdtimeout; static int wdunwedge(struct disk *du); static int wdwait(struct disk *du, u_char bits_wanted, int timeout); + /*void wdintr(int unit);*/ struct isa_driver wdcdriver = { wdprobe, wdattach, "wdc", *************** *** 249,254 **** --- 261,392 ---- #endif + #if NCARD > 0 + #include + #include + #include + /* + * PC-Card (PCMCIA) specific code. + */ + static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ + static void wdunload(struct pccard_devinfo *); /* Disable driver */ + static int wdinit(struct pccard_devinfo *); /* Init. driver */ + static int wdprobe_pccard(struct isa_device *); /* Probe PC-card */ + + static struct pccard_device wdinfo = + { + "wdc", + wdinit, + wdunload, + card_intr, + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + }; + + DATA_SET(pccarddrv_set, wdinfo); + + static int static_init = 1; + static int lunit_in_use = 0; + static int ctrlr_in_use = 0; + + /* + * Initialize the device - called from Slot manager. + * if first is set, then initially check for + * the device's existence before initialising it. + * Once initialised, the device table may be set up. + */ + static int + wdinit(struct pccard_devinfo *devi) + { + /* + * dynamic configuration mode + */ + static_init = 0; + /* + * validate unit number. + */ + if (devi->pd_unit >= NWDC) + return(ENODEV); + /* + * Probe the device. If a value is returned, the + * device was found at the location. + */ + if (wdprobe_pccard(&devi->isahd)==0) { + printf("Probe Failed\n"); + return(ENXIO); + } + if (wdattach(&devi->isahd)==0) { + printf("Attach Failed\n"); + return(ENXIO); + } + /* + * XXX TODO: + * If it was already inited before, the device structure + * should be already initialised. Here we should + * reset (and possibly restart) the hardware, but + * I am not sure of the best way to do this... + */ + return(0); + } + + /* + * wdunload - unload the driver and clear the table. + * XXX TODO: + * This is called usually when the card is ejected, but + * can be caused by the modunload of a controller driver. + * The idea is reset the driver's view of the device + * and ensure that any driver entry points such as + * read and write do not hang. + */ + static void + wdunload(struct pccard_devinfo *devi) + { + int ctrlr = devi->pd_unit; + int lunit; + + for (lunit=0; lunitdk_ctrlr == ctrlr && + wddrives[lunit]->dk_port == devi->pd_iobase ) { + lunit_in_use &= ~(1<pd_iobase); + #endif + + printf("wdc%d: unloading -- ", ctrlr); + if (wdtab[ctrlr].b_active != 0) + printf("damage!\n"); + else + printf("done\n"); + } + + /* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ + static int + card_intr(struct pccard_devinfo *devi) + { + wdintr(devi->pd_unit); + return(1); + } + + static int + wdprobe_pccard(struct isa_device *isa_dev) + { + return wdprobe(isa_dev); + } + + #endif /* NCARD > 0 */ + + + /* * Here we use the pci-subsystem to find out, whether there is * a cmd640b-chip attached on this pci-bus. This public routine *************** *** 274,279 **** --- 412,425 ---- if (unit >= NWDC) return (0); + #if NCARD > 0 + /* + * If PC-Card probe required, then register driver with + * slot manager. + */ + if (!static_init && (ctrlr_in_use & (1< 0 */ du = malloc(sizeof *du, M_TEMP, M_NOWAIT); if (du == NULL) *************** *** 281,287 **** bzero(du, sizeof *du); du->dk_ctrlr = dvp->id_unit; du->dk_port = dvp->id_iobase; ! /* check if we have registers that work */ outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */ --- 427,441 ---- bzero(du, sizeof *du); du->dk_ctrlr = dvp->id_unit; du->dk_port = dvp->id_iobase; ! du->dk_altsts = wd_altsts; ! du->dk_ctlr = wd_ctlr; ! du->dk_digin = wd_digin; ! ! if (dvp->id_flags & WDOPT_PACKED) { ! du->dk_altsts -= 0x1f8; ! du->dk_ctlr -= 0x1f8; ! du->dk_digin -= 0x1f8; ! } /* check if we have registers that work */ outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */ *************** *** 299,304 **** --- 453,460 ---- if (wdreset(du) == 0) goto reset_ok; #ifdef ATAPI + if (dvp->id_flags & WDOPT_BROKEN_SIGNATURE) + goto reset_ok; /* test for ATAPI signature */ outb(du->dk_port + wd_sdh, WDSD_IBM); /* master */ if (inb(du->dk_port + wd_cyl_lo) == 0x14 && *************** *** 361,366 **** --- 517,525 ---- } + #if NCARD > 0 + ctrlr_in_use |= (1< 0 */ free(du, M_TEMP); return (IO_WDCSIZE); *************** *** 381,386 **** --- 540,550 ---- int unit, lunit; struct isa_device *wdup; struct disk *du; + #if NCARD > 0 + static int once_registered = 0; + static int old_dkunit[NWD]; + int valid_units = 0; + #endif /* NCARD > 0 */ if (dvp->id_unit >= NWDC) return (0); *************** *** 402,417 **** if (wdup->id_iobase != dvp->id_iobase) continue; lunit = wdup->id_unit; if (lunit >= NWD) continue; unit = wdup->id_physid; ! du = malloc(sizeof *du, M_TEMP, M_NOWAIT); if (du == NULL) continue; if (wddrives[lunit] != NULL) panic("drive attached twice"); wddrives[lunit] = du; bufq_init(&drive_queue[lunit]); bzero(du, sizeof *du); --- 566,603 ---- if (wdup->id_iobase != dvp->id_iobase) continue; lunit = wdup->id_unit; + + #if NCARD > 0 + /* + * XXX + * for PCMCIA Flash ATA/Type III HDD cards. + * HOSOKAWA, Tatsumi + */ + if (lunit_in_use & (1< 0 */ + if (lunit >= NWD) continue; unit = wdup->id_physid; ! #if NCARD > 0 ! du = wddrives[lunit]; ! if (du == NULL) ! du = malloc(sizeof *du, M_TEMP, M_NOWAIT); ! if (du == NULL) ! continue; ! #else /* NCARD > 0 */ du = malloc(sizeof *du, M_TEMP, M_NOWAIT); if (du == NULL) continue; if (wddrives[lunit] != NULL) panic("drive attached twice"); + #endif /* NCARD > 0 */ wddrives[lunit] = du; bufq_init(&drive_queue[lunit]); bzero(du, sizeof *du); *************** *** 426,431 **** --- 612,626 ---- du->dk_unit = unit; du->dk_lunit = lunit; du->dk_port = dvp->id_iobase; + du->dk_altsts = wd_altsts; + du->dk_ctlr = wd_ctlr; + du->dk_digin = wd_digin; + + if (dvp->id_flags & WDOPT_PACKED) { + du->dk_altsts -= 0x1f8; + du->dk_ctlr -= 0x1f8; + du->dk_digin -= 0x1f8; + } /* * Use the individual device flags or the controller *************** *** 471,476 **** --- 666,678 ---- */ wdtimeout(du); + #if NCARD > 0 + lunit_in_use |= (1< 0 */ #ifdef DEVFS mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART); du->dk_bdev = devfs_add_devswf(&wd_bdevsw, mynor, *************** *** 492,501 **** --- 694,715 ---- * according to iostat. */ dk_wpms[dk_ndrive] = 4 * 1024 * 1024 / 2; + #if NCARD > 0 + old_dkunit[lunit] = + #endif /* NCARD > 0 */ du->dk_dkunit = dk_ndrive++; } else { + #if NCARD > 0 + old_dkunit[lunit] = + #endif /* NCARD > 0 */ du->dk_dkunit = -1; } + #if NCARD > 0 + } else { + /* reuse previous dk_dkunit */ + du->dk_dkunit = old_dkunit[lunit]; + } + #endif /* NCARD > 0 */ } else { free(du, M_TEMP); wddrives[lunit] = NULL; *************** *** 506,525 **** * Probe all free IDE units, searching for ATAPI drives. */ for (unit=0; unit<2; ++unit) { for (lunit=0; lunitdk_ctrlr == dvp->id_unit && wddrives[lunit]->dk_unit == unit) goto next; #ifdef CMD640 if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase)) atapictrlr = dvp->id_unit; ! #else atapi_attach (dvp->id_unit, unit, dvp->id_iobase); ! #endif next: ; } ! #endif /* * Discard any interrupts generated by wdgetctlr(). wdflushirq() * doesn't work now because the ambient ipl is too high. --- 720,759 ---- * Probe all free IDE units, searching for ATAPI drives. */ for (unit=0; unit<2; ++unit) { + #if NCARD > 0 + for (lunit=0; lunitdk_ctrlr == dvp->id_unit && + wddrives[lunit]->dk_unit == unit) + goto next; + #else /* NCARD > 0 */ for (lunit=0; lunitdk_ctrlr == dvp->id_unit && wddrives[lunit]->dk_unit == unit) goto next; + #endif /* NCARD > 0 */ #ifdef CMD640 + #if NCARD > 0 + if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase)) { + atapictrlr = dvp->id_unit; + valid_units++; + } + #else /* NCARD > 0 */ if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase)) atapictrlr = dvp->id_unit; ! #endif /* NCARD > 0 */ ! #else /* CMD640 */ ! #if NCARD > 0 ! if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase)) ! valid_units++; ! #else /* NCARD > 0 */ atapi_attach (dvp->id_unit, unit, dvp->id_iobase); ! #endif /* NCARD > 0 */ ! #endif /* CMD640 */ next: ; } ! #endif /* ATAPI */ /* * Discard any interrupts generated by wdgetctlr(). wdflushirq() * doesn't work now because the ambient ipl is too high. *************** *** 534,539 **** --- 768,777 ---- wdtab[dvp->id_unit].b_active = 2; #endif + #if NCARD > 0 + if (!static_init && valid_units == 0) + return (0); /* no valid unit found */ + #endif /* NCARD > 0 */ return (1); } *************** *** 757,763 **** (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount, blknum); else ! printf(" %d)%x", du->dk_skip, inb(du->dk_port + wd_altsts)); #endif lp = &du->dk_dd; --- 995,1001 ---- (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount, blknum); else ! printf(" %d)%x", du->dk_skip, inb(du->dk_port + du->dk_altsts)); #endif lp = &du->dk_dd; *************** *** 865,871 **** printf("cylin %ld head %ld sector %ld addr %x sts %x\n", cylin, head, sector, (int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, ! inb(du->dk_port + wd_altsts)); #endif } --- 1103,1109 ---- printf("cylin %ld head %ld sector %ld addr %x sts %x\n", cylin, head, sector, (int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, ! inb(du->dk_port + du->dk_altsts)); #endif } *************** *** 1165,1170 **** --- 1403,1412 ---- lunit = dkunit(dev); if (lunit >= NWD || dktype(dev) != 0) return (ENXIO); + #if NCARD > 0 + if ((lunit_in_use & (1< 0 */ du = wddrives[lunit]; if (du == NULL) return (ENXIO); *************** *** 1870,1875 **** --- 2112,2120 ---- lunit = dkunit(dev); /* eventually support floppies? */ part = dkpart(dev); if (lunit >= NWD || (du = wddrives[lunit]) == NULL + #if NCARD > 0 + || (lunit_in_use & (1< 0 */ || du->dk_state < OPEN || (lp = dsgetlabel(dev, du->dk_slices)) == NULL) return (ENXIO); *************** *** 2084,2092 **** wdc = du->dk_port; (void)wdwait(du, 0, TIMEOUT); ! outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST); DELAY(10 * 1000); ! outb(wdc + wd_ctlr, WDCTL_IDS); #ifdef ATAPI if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) err = 1; /* no IDE drive found */ --- 2329,2337 ---- wdc = du->dk_port; (void)wdwait(du, 0, TIMEOUT); ! outb(wdc + du->dk_ctlr, WDCTL_IDS | WDCTL_RST); DELAY(10 * 1000); ! outb(wdc + du->dk_ctlr, WDCTL_IDS); #ifdef ATAPI if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) err = 1; /* no IDE drive found */ *************** *** 2098,2104 **** || (du->dk_error = inb(wdc + wd_error)) != 0x01) return (1); #endif ! outb(wdc + wd_ctlr, WDCTL_4BIT); return (err); } --- 2343,2349 ---- || (du->dk_error = inb(wdc + wd_error)) != 0x01) return (1); #endif ! outb(wdc + du->dk_ctlr, WDCTL_4BIT); return (err); } Index: PAO/sys/i386/isa/wfd.c diff -c PAO/sys/i386/isa/wfd.c:1.1.1.2 PAO/sys/i386/isa/wfd.c:1.1.1.2.4.1 *** PAO/sys/i386/isa/wfd.c:1.1.1.2 Fri Jul 24 19:18:54 1998 --- PAO/sys/i386/isa/wfd.c Sun Dec 6 07:48:01 1998 *************** *** 23,29 **** * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ! * $Id: wfd.c,v 1.1.1.2 1998/07/24 10:18:54 nakagawa Exp $ */ /* --- 23,29 ---- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ! * $Id: wfd.c,v 1.1.1.2.4.1 1998/12/05 22:48:01 itojun Exp $ */ /* *************** *** 72,77 **** --- 72,83 ---- static #endif int wfdattach(struct atapi*, int, struct atapi_params*, int); + #ifdef ATAPI_DETACH + #ifndef ATAPI_STATIC + static + #endif + int wfddetach(struct atapi*, int, struct atapi_params*, int); + #endif /* ATAPI_DETACH */ #define NUNIT (NWDC*2) /* Max. number of devices */ #define UNIT(d) ((minor(d) >> 3) & 3) /* Unit part of minor device number */ *************** *** 143,149 **** --- 149,159 ---- }; struct wfd *wfdtab[NUNIT]; /* Drive info by unit number */ + #ifndef ATAPI_DETACH static int wfdnlun = 0; /* Number of configured drives */ + #else /* ATAPI_DETACH */ + static int wfd_unit_use = 0; /* Number of configured drives */ + #endif /* ATAPI_DETACH */ static void wfd_start (struct wfd *t); static void wfd_done (struct wfd *t, struct buf *bp, int resid, *************** *** 182,191 **** --- 192,212 ---- #ifdef DEVFS int mynor; #endif + #ifndef ATAPI_DETACH if (wfdnlun >= NUNIT) { printf ("wfd: too many units\n"); return (0); } + #else /* ATAPI_DETACH */ + for (lun=0; lun < NUNIT; lun++) { + if (!(wfd_unit_use & (1 << lun))) + break; + } + if (lun >= NUNIT) { + printf ("wfd: too many units\n"); + return (0); + } + #endif /* ATAPI_DETACH */ if (!atapi_request_immediate) { printf("wfd: configuration error, ATAPI core code not present!\n"); printf("wfd: check `options ATAPI_STATIC' in your kernel config file!\n"); *************** *** 196,207 **** --- 217,237 ---- printf ("wfd: out of memory\n"); return (0); } + #ifndef ATAPI_DETACH wfdtab[wfdnlun] = t; + #else /* ATAPI_DETACH */ + wfdtab[lun] = t; + #endif /* ATAPI_DETACH */ bzero(t, sizeof (struct wfd)); bufq_init(&t->buf_queue); t->ata = ata; t->unit = unit; + #ifndef ATAPI_DETACH lun = t->lun = wfdnlun++; + #else /* ATAPI_DETACH */ + t->lun = lun; + wfd_unit_use |= (1 << lun); + #endif /* ATAPI_DETACH */ t->param = ap; t->flags = F_MEDIA_CHANGED; t->refcnt = 0; *************** *** 265,270 **** --- 295,338 ---- return (1); } + #ifdef ATAPI_DETACH + #ifndef ATAPI_STATIC + static + #endif + int + wfddetach (struct atapi *ata, int unit, struct atapi_params *ap, int debug) + { + struct wfd **t; + int lun; + + for (lun=0; lun < NUNIT; lun++) { + if ((wfd_unit_use & (1 << lun))) { + t = wfdtab + lun; + if ((*t)->ata->port == ata->port && + (*t)->ata->ctrlr == ata->ctrlr && + (*t)->unit == unit) + break; + } + } + if (lun >= NUNIT) { + printf ("wfd: not found unit\n"); + return (0); + } + + t = wfdtab + lun; + if (((*t)->flags & F_BOPEN) || (*t)->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + (*t)->ata->attached[(*t)->unit] = 0; + free (*t, M_TEMP); + wfdtab[lun] = NULL; + + wfd_unit_use &= ~(1 << lun); + + return 0; + } + #endif /* ATAPI_DETACH */ + void wfd_describe (struct wfd *t) { int no_print = 0; *************** *** 340,347 **** --- 408,420 ---- /* Check that the device number is legal * and the ATAPI driver is loaded. */ + #ifndef ATAPI_DETACH if (lun >= wfdnlun || ! atapi_request_immediate) return (ENXIO); + #else /* ATAPI_DETACH */ + if (!(wfd_unit_use & (1 << lun)) || ! atapi_request_immediate) + return (ENXIO); + #endif /* ATAPI_DETACH */ t = wfdtab[lun]; t->flags &= ~F_MEDIA_CHANGED; *************** *** 790,795 **** --- 863,869 ---- { struct wfd **t; + #ifndef ATAPI_DETACH for (t=wfdtab; tflags & F_BOPEN) || (*t)->refcnt) /* The device is opened, cannot unload the driver. */ *************** *** 799,804 **** --- 873,894 ---- free (*t, M_TEMP); } wfdnlun = 0; + #else /* ATAPI_DETACH */ + for (int lun=0; lun < NUNIT; ++lun) + if (wfd_unit_use & (1 << lun)) { + t = wfdtab + lun; + if (((*t)->flags & F_BOPEN) || (*t)->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + } + for (int lun=0; lun < NUNIT; ++lun) + if (wfd_unit_use & (1 << lun)) { + t = wfdtab + lun; + (*t)->ata->attached[(*t)->unit] = 0; + free (*t, M_TEMP); + } + wfd_unit_use = 0; + #endif /* ATAPI_DETACH */ bzero (wfdtab, sizeof(wfdtab)); return 0; } Index: PAO/sys/i386/isa/ic/i82593.h diff -c /dev/null PAO/sys/i386/isa/ic/i82593.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:11 1998 --- PAO/sys/i386/isa/ic/i82593.h Sun Dec 6 07:48:16 1998 *************** *** 0 **** --- 1,223 ---- + /* + * Definitions for Intel 82593 CSMA/CD Core LAN Controller + * The definitions are taken from the 1992 users manual with Intel + * order number 297125-001. + * + * Copyright 1994, Anders Klemets + * + * I permit including this code in the releases of FreeBSD. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The names of the authors may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef _PCMCIA_I82593_H + #define _PCMCIA_I82593_H + + /* Intel 82593 CSMA/CD Core LAN Controller */ + + /* Port 0 Command Register definitions */ + + /* Execution operations */ + #define OP0_NOP 0 /* CHNL = 0 */ + #define OP0_SWIT_TO_PORT_1 0 /* CHNL = 1 */ + #define OP0_IA_SETUP 1 + #define OP0_CONFIGURE 2 + #define OP0_MC_SETUP 3 + #define OP0_TRANSMIT 4 + #define OP0_TDR 5 + #define OP0_DUMP 6 + #define OP0_DIAGNOSE 7 + #define OP0_TRANSMIT_NO_CRC 9 + #define OP0_RETRANSMIT 12 + #define OP0_ABORT 13 + /* Reception operations */ + #define OP0_RCV_ENABLE 8 + #define OP0_RCV_DISABLE 10 + #define OP0_STOP_RCV 11 + /* Status pointer control operations */ + #define OP0_FIX_PTR 15 /* CHNL = 1 */ + #define OP0_RLS_PTR 15 /* CHNL = 0 */ + #define OP0_RESET 14 + + #define CR0_CHNL (1 << 4) /* 0=Channel 0, 1=Channel 1 */ + #define CR0_STATUS_0 0x00 + #define CR0_STATUS_1 0x20 + #define CR0_STATUS_2 0x40 + #define CR0_STATUS_3 0x60 + #define CR0_INT_ACK (1 << 7) /* 0=No ack, 1=acknowledge */ + + /* Port 0 Status Register definitions */ + + #define SR0_NO_RESULT 0 /* dummy */ + #define SR0_EVENT_MASK 0x0f + #define SR0_IA_SETUP_DONE 1 + #define SR0_CONFIGURE_DONE 2 + #define SR0_MC_SETUP_DONE 3 + #define SR0_TRANSMIT_DONE 4 + #define SR0_TDR_DONE 5 + #define SR0_DUMP_DONE 6 + #define SR0_DIAGNOSE_PASSED 7 + #define SR0_TRANSMIT_NO_CRC_DONE 9 + #define SR0_RETRANSMIT_DONE 12 + #define SR0_EXECUTION_ABORTED 13 + #define SR0_END_OF_FRAME 8 + #define SR0_RECEPTION_ABORTED 10 + #define SR0_DIAGNOSE_FAILED 15 + #define SR0_STOP_REG_HIT 11 + + #define SR0_CHNL (1 << 4) + #define SR0_EXECUTION (1 << 5) + #define SR0_RECEPTION (1 << 6) + #define SR0_INTERRUPT (1 << 7) + + #define SR3_EXEC_STATE_MASK 0x03 + #define SR3_EXEC_IDLE 0 + #define SR3_TX_ABORT_IN_PROGRESS 1 + #define SR3_EXEC_ACTIVE 2 + #define SR3_ABORT_IN_PROGRESS 3 + #define SR3_EXEC_CHNL (1 << 2) + #define SR3_STP_ON_NO_RSRC (1 << 3) + #define SR3_RCVING_NO_RSRC (1 << 4) + #define SR3_RCV_STATE_MASK 0x60 + #define SR3_RCV_IDLE 0x00 + #define SR3_RCV_READY 0x20 + #define SR3_RCV_ACTIVE 0x40 + #define SR3_RCV_STOP_IN_PROG 0x60 + #define SR3_RCV_CHNL (1 << 7) + + /* Port 1 Command Register definitions */ + + #define OP1_NOP 0 + #define OP1_SWIT_TO_PORT_0 1 + #define OP1_INT_DISABLE 2 + #define OP1_INT_ENABLE 3 + #define OP1_SET_TS 5 + #define OP1_RST_TS 7 + #define OP1_POWER_DOWN 8 + #define OP1_RESET_RING_MNGMT 11 + #define OP1_RESET 14 + #define OP1_SEL_RST 15 + + #define CR1_STATUS_4 0x00 + #define CR1_STATUS_5 0x20 + #define CR1_STATUS_6 0x40 + #define CR1_STOP_REG_UPDATE (1 << 7) + + /* Receive frame status bits */ + + #define RX_RCLD (1 << 0) + #define RX_IA_MATCH (1 << 1) + #define RX_NO_AD_MATCH (1 << 2) + #define RX_NO_SFD (1 << 3) + #define RX_SRT_FRM (1 << 7) + #define RX_OVRRUN (1 << 8) + #define RX_ALG_ERR (1 << 10) + #define RX_CRC_ERR (1 << 11) + #define RX_LEN_ERR (1 << 12) + #define RX_RCV_OK (1 << 13) + #define RX_TYP_LEN (1 << 15) + + /* Transmit status bits */ + + #define TX_NCOL_MASK 0x0f + #define TX_FRTL (1 << 4) + #define TX_MAX_COL (1 << 5) + #define TX_HRT_BEAT (1 << 6) + #define TX_DEFER (1 << 7) + #define TX_UND_RUN (1 << 8) + #define TX_LOST_CTS (1 << 9) + #define TX_LOST_CRS (1 << 10) + #define TX_LTCOL (1 << 11) + #define TX_OK (1 << 13) + #define TX_COLL (1 << 15) + + + struct i82593_conf_block { + u_char fifo_limit : 4, + forgnesi : 1, + fifo_32 : 1, + d6mod : 1, + throttle_enb : 1; + u_char throttle : 6, + cntrxint : 1, + contin : 1; + u_char addr_len : 3, + acloc : 1, + preamb_len : 2, + loopback : 2; + u_char lin_prio : 3, + tbofstop : 1, + exp_prio : 3, + bof_met : 1; + u_char : 4, + ifrm_spc : 4; + u_char : 5, + slottim_low : 3; + u_char slottim_hi : 3, + : 1, + max_retr : 4; + u_char prmisc : 1, + bc_dis : 1, + : 1, + crs_1 : 1, + nocrc_ins : 1, + crc_1632 : 1, + : 1, + crs_cdt : 1; + u_char cs_filter : 3, + crs_src : 1, + cd_filter : 3, + : 1; + u_char : 2, + min_fr_len : 6; + u_char lng_typ : 1, + lng_fld : 1, + rxcrc_xf : 1, + artx : 1, + sarec : 1, + tx_jabber : 1, /* why is this called max_len in the manual? */ + hash_1 : 1, + lbpkpol : 1; + u_char : 6, + fdx : 1, + : 1; + u_char dummy_6 : 6, /* supposed to be ones */ + mult_ia : 1, + dis_bof : 1; + u_char dummy_1 : 1, /* supposed to be one */ + tx_ifs_retrig : 2, + mc_all : 1, + rcv_mon : 2, + frag_acpt : 1, + tstrttrs : 1; + u_char fretx : 1, + runt_eop : 1, + hw_sw_pin : 1, + big_endn : 1, + syncrqs : 1, + sttlen : 1, + tx_eop : 1, + rx_eop : 1; + u_char rbuf_size : 5, + rcvstop : 1, + : 2; + }; + + #endif _PCMCIA_I82593_H + Index: PAO/sys/i386/isa/ic/ns16550.h diff -c PAO/sys/i386/isa/ic/ns16550.h:1.1.1.1 PAO/sys/i386/isa/ic/ns16550.h:1.1.1.1.10.1 *** PAO/sys/i386/isa/ic/ns16550.h:1.1.1.1 Thu Dec 11 22:37:09 1997 --- PAO/sys/i386/isa/ic/ns16550.h Sun Dec 6 07:48:17 1998 *************** *** 37,55 **** /* * NS16550 UART registers */ - #ifdef PC98 - #define com_data 0x000 /* data register (R/W) */ - #define com_dlbl 0x000 /* divisor latch low (W) */ - #define com_dlbh 0x100 /* divisor latch high (W) */ - #define com_ier 0x100 /* interrupt enable (W) */ - #define com_iir 0x200 /* interrupt identification (R) */ - #define com_fifo 0x200 /* FIFO control (W) */ - #define com_lctl 0x300 /* line control register (R/W) */ - #define com_cfcr 0x300 /* line control register (R/W) */ - #define com_mcr 0x400 /* modem control register (R/W) */ - #define com_lsr 0x500 /* line status register (R/W) */ - #define com_msr 0x600 /* modem status register (R/W) */ - #else /* IBM-PC */ #define com_data 0 /* data register (R/W) */ #define com_dlbl 0 /* divisor latch low (W) */ #define com_dlbh 1 /* divisor latch high (W) */ --- 37,42 ---- *************** *** 61,64 **** #define com_mcr 4 /* modem control register (R/W) */ #define com_lsr 5 /* line status register (R/W) */ #define com_msr 6 /* modem status register (R/W) */ - #endif /* PC98 */ --- 48,50 ---- Index: PAO/sys/i386/isa/snd/CARDS diff -c PAO/sys/i386/isa/snd/CARDS:1.1.1.3 PAO/sys/i386/isa/snd/CARDS:1.1.1.3.2.1 *** PAO/sys/i386/isa/snd/CARDS:1.1.1.3 Sat Dec 5 05:38:48 1998 --- PAO/sys/i386/isa/snd/CARDS Mon Dec 21 20:47:14 1998 *************** *** 305,307 **** --- 305,308 ---- supported at the moment. -------------------------------------------------------------------- + $Id: CARDS,v 1.1.1.3.2.1 1998/12/21 11:47:14 sanpei Exp $ Index: PAO/sys/i386/isa/snd/HISTORY.ESS diff -c /dev/null PAO/sys/i386/isa/snd/HISTORY.ESS:1.1.2.1 *** /dev/null Fri Dec 25 10:51:14 1998 --- PAO/sys/i386/isa/snd/HISTORY.ESS Mon Dec 21 20:47:15 1998 *************** *** 0 **** --- 1,5 ---- + $Id: HISTORY.ESS,v 1.1.2.1 1998/12/21 11:47:15 sanpei Exp $ + + Mon Dec 21 19:46:11 JST 1998 + o merge 1.8.2.7 version changes of sound.c + and compile 2.2.7-RELEASE and 2.2.8-RELEASE systems Index: PAO/sys/i386/isa/snd/HISTORY.ESS.jp diff -c /dev/null PAO/sys/i386/isa/snd/HISTORY.ESS.jp:1.1.2.1 *** /dev/null Fri Dec 25 10:51:15 1998 --- PAO/sys/i386/isa/snd/HISTORY.ESS.jp Mon Dec 21 20:47:16 1998 *************** *** 0 **** --- 1,60 ---- + Mon Dec 21 19:46:11 JST 1998 + o 2.2.8-RELEASE $B$G(B compile $B$G$-$J$$LdBj$r2r7h(B + + Mon Nov 23 09:45:44 JST 1998 + $B at 0x220 irq 5 dma 1:1 + ~~~~~~~~~~~ + + FreeBSD-users-jp 35506 $B$N9uBt$5$s$NJQ99$r(B merge + + $B2r7h$7$?LdBj(B + + *(4) Windows95 $B$r%V!<%H$7$F$+$i!$$=$N8e$KEE8;$r(B off + * $B$;$:(B FreeBSD $B$r%V!<%H$9$k$H(B mixer $B$N(B master volume + * $B$,$*$+$7$J@_Dj$K$J$C$?$^$^@)8fITG=$K$J$k(B(FMV 5133NP/W + * $B$@$1$+$b$7$l$^$;$s(B, sb0 $B$G$bH/@8(B, $B$H$j$"$($:$NBP:v$O(B + * Win95,FreeBSD $B$r8r8_$K(B reboot $B$r7+$jJV$9(B :-<)$B!%(B + + + *(3) $B2;@<$r:F@8$9$k%"%W%j%1!<%7%g%s$r=*N;$5$;$k$H!$(B + * $B:G8e$NJ}$N2;$,%k!<%W$7$F:F@8$5$l$C$Q$J$7$K$J$k(B + * $B$3$H$,$"$k!%(B(^z $B$9$k$H(B 100% $B:F8=(B) + + *(7) $B8=>u$G$O(B ESS1879 $B$r(B 1878 $B$HI=<($9$k(B. + + $B/!9Fq$"$j(B + *(1) mpg123 $B$G6J$rJ#?t;XDj$7$F$$$k$H$-$K(B, $B;~!9(B, + * $B $B$^$@2r7h$7$F$$$J$$$h$&$G$9(B. $BIQEY$O8:$C$?$,(B, + * mpg123 $B$GJ#?t6J;XDj;~$K(B, [Ctrl]+[C] $B$r$7$F(B + * $B$I$s$I$s@Z$jBX$($k$H$-$K$*$-$?(B. + + *(2) $B:F@8$r;O$a$k$H$-$K(B, $BJQ$J2;$,=P$k(B. + * (dsp $B$N(B reset, setup $B;~$K(B mute $B=hM}$,IT==J,(B?) + + Fri Nov 20 21:10:11 JST 1998 + FreeBSD-stable tree $B$rMxMQ$9$k$h$&$K$7$?(B + $BF1;~$K(B x11amp 0.8 $B$r;H$($k$h$&$K$J$j$^$7$?(B + + $Id: HISTORY.ESS.jp,v 1.1.2.1 1998/12/21 11:47:16 sanpei Exp $ Index: PAO/sys/i386/isa/snd/README diff -c PAO/sys/i386/isa/snd/README:1.1.1.3 PAO/sys/i386/isa/snd/README:1.1.1.3.2.1 *** PAO/sys/i386/isa/snd/README:1.1.1.3 Sat Dec 5 05:38:51 1998 --- PAO/sys/i386/isa/snd/README Mon Dec 21 20:47:17 1998 *************** *** 294,296 **** --- 294,298 ---- the product. Too bad that no one of the chip/card manufacturers I have contacted by email regarding missing or inconsistent documentation on their products did even care to reply to my messages. + + $Id: README,v 1.1.1.3.2.1 1998/12/21 11:47:17 sanpei Exp $ Index: PAO/sys/i386/isa/snd/README.ESS diff -c /dev/null PAO/sys/i386/isa/snd/README.ESS:1.1.2.1 *** /dev/null Fri Dec 25 10:51:15 1998 --- PAO/sys/i386/isa/snd/README.ESS Mon Dec 21 20:47:19 1998 *************** *** 0 **** --- 1,57 ---- + EES sound chip Sound Driver + + $Id: README.ESS,v 1.1.2.1 1998/12/21 11:47:19 sanpei Exp $ + + Our Goal: + This patch has some miner problems as below. We + hope to fix these and at last we merge to pcm driver. + + Contact: + MIHIRA Yoshiro sanpei@sanpei.org, sanpei@jp.freebsd.org + + Latest driver: + http://www.jp.freebsd.org/~sanpei/ + + Supported NOTE-PCs which use ESS Sound Chip: + Sotec WinBookPro ESS688 + ToshibaSatellite Pro 430CDT + ESS688 + DEC HiNote Ultra II CTS-5120 + ESS1688 + Hyperbook 750+ ESS1868 + Compaq DeskPro ESS1869 + NEC MobioNX ESS1869 + FM/V Biblo NP/W ESS1878 + Sony VAIO-505 ESS1878 + SONY VAIO PCG-707 ESS1878 + SONY VAIO PCG-803 ESS1879 + FM-V Biblo NC313 ESS1879 + Chandra2 ESS1879 + (your report are welcome) + + Current Status: + This driver support up to 44KHz/16bit mode. And + fixed problem that sound only come out from left + channel, buggy mixer. + + Example: + mpg123 -v mp3_filename + + Old pcm and sb driver: + Audio: 2:1 conversion, rate: 22050, encoding: unsigned 8 bit, channels: 2 + ~~~~~ ~~~~~ + This driver: + Audio: 1:1 conversion, rate: 44100, encoding: signed 16 bit, channels: 2 + ~~~~~ ~~~~~~ + Current Problem: + Some time (CPU was heavy load?), sound change to white + noise. + And also with using mpg123 player and selected some files, + when one file is ended and change to another file, + also sound change to white noise... + + DATA SHEETS: + ftp://ftp.esstech.com.tw/Document/ + or + http://alsa.jcu.cz/alsa/ftp/manuals/ess/ + Index: PAO/sys/i386/isa/snd/README.ESS.jp diff -c /dev/null PAO/sys/i386/isa/snd/README.ESS.jp:1.1.2.1 *** /dev/null Fri Dec 25 10:51:16 1998 --- PAO/sys/i386/isa/snd/README.ESS.jp Mon Dec 21 20:47:20 1998 *************** *** 0 **** --- 1,67 ---- + Luigi Sound Driver $B$X$N(B ESS $B7O%A%C%WBP1~(B pcm driver $B%-%C%H(B + + $Id: README.ESS.jp,v 1.1.2.1 1998/12/21 11:47:20 sanpei Exp $ + + $BL\I8(B + $B8=:_$NLdBjE@$r2~NI$7$F(B, $BK\2H$N(B source tree $B$KF~$l$k(B. + + $Bl=j(B + http://www.jp.freebsd.org/~sanpei/ + + ESS $B7O$r;H$C$?(B NOTE-PC + $BF0:n3NG'%^%7%s(B + Sotec WinBookPro ESS688 + ToshibaSatellite Pro 430CDT + ESS688 + DEC HiNote Ultra II CTS-5120 + ESS1688 + Hyperbook 750+ ESS1868 + Compaq DeskPro ESS1869 + NEC MobioNX ESS1869 + FM/V Biblo NP/W ESS1878 + Sony VAIO-505 $B7O(B ESS1878 + SONY VAIO PCG-707 ESS1878 + SONY VAIO PCG-803 ESS1879 + FM-V Biblo NC313 ESS1879 + Chandra2 $B7O(B($B"((B1) ESS1879 + $BEy(B($BDI2C>pJs5a$`(B) + + $B"((B 1 Chandra2 $B7O(B + IBM ThinkPad 235, HITACHI FLORA Priusnote 210{g|h}, EPSON TK-400, etc... + + $BBP1~%=!<%9(B + FreeBSD-stable $BMQ$G$9(B. $B;DG0$J$,$i(B FreeBSD-current $BMQ$O(B + $BMQ0U$G$-$F$$$^$;$s(B. $B:n$l$k?M$OO"Mm$/$@$5$$(B. + + $B8=:_$N2~NIE@(B + Luigi driver $B$G$O(B, ESS 1868,688 $B$J$I$X$NBP1~$,IT==J,$G$9(B. + dsp $B$G$O(B 22KHz, 8bit $B$G$7$+;H$($^$;$s$G$7$?(B. + $B$^$?(B, 22KHz, 8bit $B$G$b(B, $B%I%i%$%P$N%P%0$G(B, $B:8B&$+$i$7$+(B, + $B2;$,=P$J$+$C$?$j(B, $B2;NLD4@a(B(mixer)$B$,$&$^$/F0$-$^$;$s$G$7$?(B. + + $B$3$N%Q%C%A$rMQ$$$k$3$H$G(B, 44KHz, 16bit $B$,2DG=$G(B, $B2;NLD4@a$b(B + $B@5$7$/F0$-$^$9(B. + + $BMxMQNc(B + mpg123 -v mp3_filename + + Audio: 2:1 conversion, rate: 22050, encoding: unsigned 8 bit, channels: 2 + ~~~~~ ~~~~~ + Audio: 1:1 conversion, rate: 44100, encoding: signed 16 bit, channels: 2 + ~~~~~ ~~~~~~ + + $B;29M;qNA(B + DATASHEET$B$NF~ $B$^$@2r7h$7$F$$$J$$$h$&$G$9(B. $BIQEY$O8:$C$?$,(B, + mpg123 $B$GJ#?t6J;XDj;~$K(B, [Ctrl]+[C] $B$r$7$F(B + $B$I$s$I$s@Z$jBX$($k$H$-$K$*$-$?(B. + + --> $B:,K\E*$K8=:_(B DMA $BE>Aw%3!<%I$r8+D>$7Cf(B + + (5) $B%*%j%8%J%k%W%m%0%i%`$G(B ioctl(SNDCTL_DSP_SYNC) + $B$r=P$7$?$H$-$K!$(Bioctl $BFbIt$G(B sleep $B$7$?$^$^(B + $BLa$C$F$3$J$$$3$H$,$"$k!%(B + + (8) ESS1868: setting master volume control register + $B$H(B ESS1868 $B7h$aBG$A$GI=<($5$l$kLdBj(B + (ESS1869 $B$G$b(B ESS1868 $B$H$J$k(B :-< + ---> detect $B%3!<%I$r2~NIM=Dj(B Index: PAO/sys/i386/isa/snd/ad1848.c diff -c PAO/sys/i386/isa/snd/ad1848.c:1.1.1.3 PAO/sys/i386/isa/snd/ad1848.c:1.1.1.3.2.1 *** PAO/sys/i386/isa/snd/ad1848.c:1.1.1.3 Sat Dec 5 05:38:52 1998 --- PAO/sys/i386/isa/snd/ad1848.c Mon Dec 21 20:47:24 1998 *************** *** 40,45 **** --- 40,49 ---- * http://www.opti.com/ for the OPTi931 */ + /* + * $Id: ad1848.c,v 1.1.1.3.2.1 1998/12/21 11:47:24 sanpei Exp $ + */ + #include #if NPCM > 0 Index: PAO/sys/i386/isa/snd/clones.c diff -c PAO/sys/i386/isa/snd/clones.c:1.1.1.1 PAO/sys/i386/isa/snd/clones.c:1.1.1.1.8.1 *** PAO/sys/i386/isa/snd/clones.c:1.1.1.1 Sun Apr 5 07:13:41 1998 --- PAO/sys/i386/isa/snd/clones.c Mon Dec 21 20:47:26 1998 *************** *** 33,38 **** --- 33,42 ---- * in the Voxware 3.5 distribution. */ + /* + * $Id: clones.c,v 1.1.1.1.8.1 1998/12/21 11:47:26 sanpei Exp $ + */ + #include #if NPCM > 0 Index: PAO/sys/i386/isa/snd/dmabuf.c diff -c PAO/sys/i386/isa/snd/dmabuf.c:1.1.1.3 PAO/sys/i386/isa/snd/dmabuf.c:1.1.1.3.2.1 *** PAO/sys/i386/isa/snd/dmabuf.c:1.1.1.3 Sat Dec 5 05:38:54 1998 --- PAO/sys/i386/isa/snd/dmabuf.c Mon Dec 21 20:47:27 1998 *************** *** 31,36 **** --- 31,40 ---- * */ + /* + * $Id: dmabuf.c,v 1.1.1.3.2.1 1998/12/21 11:47:27 sanpei Exp $ + */ + #include #include Index: PAO/sys/i386/isa/snd/mss.h diff -c PAO/sys/i386/isa/snd/mss.h:1.1.1.2 PAO/sys/i386/isa/snd/mss.h:1.1.1.2.4.1 *** PAO/sys/i386/isa/snd/mss.h:1.1.1.2 Fri Jul 24 19:19:45 1998 --- PAO/sys/i386/isa/snd/mss.h Mon Dec 21 20:47:27 1998 *************** *** 9,14 **** --- 9,18 ---- */ /* + * $Id: mss.h,v 1.1.1.2.4.1 1998/12/21 11:47:27 sanpei Exp $ + */ + + /* * The codec part of the board is seen as a set of 4 registers mapped Index: PAO/sys/i386/isa/snd/sb_dsp.c diff -c PAO/sys/i386/isa/snd/sb_dsp.c:1.1.1.3 PAO/sys/i386/isa/snd/sb_dsp.c:1.1.1.3.2.1 *** PAO/sys/i386/isa/snd/sb_dsp.c:1.1.1.3 Sat Dec 5 05:38:55 1998 --- PAO/sys/i386/isa/snd/sb_dsp.c Mon Dec 21 20:47:28 1998 *************** *** 35,40 **** --- 35,44 ---- */ /* + * $Id: sb_dsp.c,v 1.1.1.3.2.1 1998/12/21 11:47:28 sanpei Exp $ + */ + + /* * use this as a template file for board-specific drivers. * The next two lines (and the final #endif) are in all drivers: */ *************** *** 76,81 **** --- 80,86 ---- u_int sb_get_byte(int io_base); int ess_write(int io_base, u_char reg, int val); int ess_read(int io_base, u_char reg); + void ess_cont_getmixer(int io_base, u_int port, u_char *buf, int num); /* * Then put here the descriptors for the various boards supported *************** *** 324,329 **** --- 329,342 ---- if ( reason & 1 ) { /* possibly a write interrupt */ if ( d->dbuf_out.dl ) dsp_wrintr(d); + else if (d->bd_flags & BD_F_ESS) { + /* + * Stop the DMA transaction. + * (based on the audio-output scenario on the spec. pp.43-44) + */ + ess_write(d->io_base, 0xb8, + ess_read(d->io_base, 0xb8) & ~1); + } } if ( reason & 2 ) { if ( d->dbuf_in.dl ) *************** *** 428,456 **** d->dbuf_in.chan = d->dbuf_out.chan; d->dbuf_out.chan = c ; } - } else if (d->bd_flags & BD_F_ESS) { - u_char c ; - if (d->play_fmt == 0) { - /* initialize for record */ - static u_char cmd[] = { - 0x51,0xd0,0x71,0xf4,0x51,0x98,0x71,0xbc - }; - ess_write(d->io_base, 0xb8, 0x0e); - c = ( ess_read(d->io_base, 0xa8) & 0xfc ) | 1 ; - if (d->flags & SND_F_STEREO) - c++ ; - ess_write(d->io_base, 0xa8, c); - ess_write(d->io_base, 0xb9, 2); /* 4bytes/transfer */ - /* - * set format in b6, b7 - */ - } else { - /* initialize for play */ - static u_char cmd[] = { - 0x80,0x51,0xd0,0x00,0x71,0xf4, - 0x80,0x51,0x98,0x00,0x71,0xbc - }; - } } reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); --- 441,446 ---- *************** *** 512,521 **** --- 502,574 ---- sb_cmd(d->io_base, c ); sb_cmd3(d->io_base, c1 , l - 1) ; } else if (d->bd_flags & BD_F_ESS) { + u_char a8 ; + u_char *cmd_ofs; + short c = -l; + + if (rd) { + /* initialize for record */ + static u_char cmd[] = { + 0x51,0xd0,0x71,0xf4,0x51,0x98,0x71,0xbc + }; + ess_write(d->io_base, 0xb8, 0x0e); + a8 = ( ess_read(d->io_base, 0xa8) & 0xfc ) | 1 ; + if (d->flags & SND_F_STEREO) + a8++ ; + ess_write(d->io_base, 0xa8, a8); + ess_write(d->io_base, 0xb9, 2); /* 4bytes/transfer */ + /* + * set format in b6, b7 + */ + cmd_ofs = cmd + ((d->flags & SND_F_STEREO) ? 4 : 0) + + ((d->rec_fmt == AFMT_S16_LE) ? 2 : 0); + ess_write(d->io_base, 0xb7, cmd_ofs[0]); + ess_write(d->io_base, 0xb7, cmd_ofs[1]); + ess_write(d->io_base, 0xb1, + (ess_read(d->io_base, 0xb1) & 0x0f) | 0x50); + ess_write(d->io_base, 0xb2, + (ess_read(d->io_base, 0xb2) & 0x0f) | 0x50); + } else { + /* initialize for play */ + static u_char cmd[] = { + 0x80,0x51,0xd0,0x00,0x71,0xf4, + 0x80,0x51,0x98,0x00,0x71,0xbc + }; + + a8 = ( ess_read(d->io_base, 0xa8) & 0xfc ) | 1 ; + if (! (d->flags & SND_F_STEREO)) + a8++; + ess_write(d->io_base, 0xa8, a8); + ess_write(d->io_base, 0xb9, 2); /* 4bytes/transfer */ + + cmd_ofs = cmd + ((d->flags & SND_F_STEREO) ? 6 : 0) + + ((d->play_fmt == AFMT_S16_LE) ? 3 : 0); + ess_write(d->io_base, 0xb6, cmd_ofs[0]); + ess_write(d->io_base, 0xb7, cmd_ofs[1]); + ess_write(d->io_base, 0xb7, cmd_ofs[2]); + + ess_write(d->io_base, 0xb1, + (ess_read(d->io_base, 0xb1) & 0x0f) | 0x50); + ess_write(d->io_base, 0xb2, + (ess_read(d->io_base, 0xb2) & 0x0f) | 0x50); + } + ess_write(d->io_base, 0xa4, (u_char)((u_short)c & 0xff)); + ess_write(d->io_base, 0xa5, (u_char)((u_short)(c >> 8) & 0xff)); + if (rd) { + ess_write(d->io_base, 0xb8, + ess_read(d->io_base, 0xb8) | 0x0f); + } else { + ess_write(d->io_base, 0xb8, + ess_read(d->io_base, 0xb8) | 0x05); + sb_cmd(d->io_base, DSP_CMD_SPKON); + } + #if 0 /* XXX this code is still incomplete */ sb_cmd2(d->io_base, 0xb8, rd ? 4 : 0xe ) ; /* auto dma */ sb_cmd2(d->io_base, 0xa8, d->flags & SND_F_STEREO ? 1 : 2) ; sb_cmd2(d->io_base, 0xb9, 2) ; /* demand dma */ + #endif + } else { /* SBPro -- stereo not supported */ u_char c ; if (!rd) *************** *** 546,554 **** case SND_CB_STOP : { int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */ ! if ( b->chan > 4 ! || (rd && d->rec_fmt == AFMT_S16_LE) ! || (!rd && d->play_fmt == AFMT_S16_LE) ) cmd = DSP_CMD_DMAPAUSE_16 ; if (d->bd_flags & BD_F_HISPEED) { --- 599,608 ---- case SND_CB_STOP : { int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */ ! if (!(d->bd_flags & BD_F_ESS) ! && (b->chan > 4 ! || (rd && d->rec_fmt == AFMT_S16_LE) ! || (!rd && d->play_fmt == AFMT_S16_LE)) ) cmd = DSP_CMD_DMAPAUSE_16 ; if (d->bd_flags & BD_F_HISPEED) { *************** *** 557,563 **** sb_cmd(d->io_base, 0xc6 ); /* enable extended ESS mode */ d->flags |= SND_F_INIT ; } else { ! sb_cmd(d->io_base, cmd); /* pause dma. */ /* * The above seems to have the undocumented side effect of * blocking the other side as well. If the other --- 611,627 ---- sb_cmd(d->io_base, 0xc6 ); /* enable extended ESS mode */ d->flags |= SND_F_INIT ; } else { ! if (d->bd_flags & BD_F_ESS) { ! /* ! * Stop after the current transfer has completed. ! * sbintr will be called later. ! * (based on the audio-output scenario) ! */ ! ess_write(d->io_base, 0xb8, ! ess_read(d->io_base, 0xb8) & ~4); ! } else { ! sb_cmd(d->io_base, cmd); /* pause dma. */ ! } /* * The above seems to have the undocumented side effect of * blocking the other side as well. If the other *************** *** 625,630 **** --- 689,695 ---- int i, x; char *fmt = NULL ; int io_base = dev->id_iobase ; + u_char ess_ident[4]; d->bd_id = 0 ; *************** *** 724,735 **** break ; } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { int rev = ess_minor & 0xf ; ! if ( rev >= 8 ) ! printf("ESS1868 (rev %d)\n", rev); ! else ! printf("ESS688 (rev %d)\n", rev); ! /* d->audio_fmt |= AFMT_S16_LE; */ /* not yet... */ ! break ; /* XXX */ } else { printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n", ess_major, ess_minor); --- 789,813 ---- break ; } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { int rev = ess_minor & 0xf ; ! if ( rev >= 8 ) { ! ess_cont_getmixer(io_base, 0x40, ess_ident, sizeof(ess_ident)); ! if (ess_ident[0] == 0x18) { ! sprintf(fmt, "ESS18%x %%d.%%d", ess_ident[1]); ! printf("ESS18%x (rev %d, native mode)\n", ess_ident[1], rev); ! } else { ! printf("ESS Chip (rev %d, %x%x)\n", rev, ess_ident[0], ess_ident[1]); ! } ! } else { ! sprintf(fmt, "ESS688 %%d.%%d"); ! printf("ESS688 (rev %d, native mode)\n", rev); ! } ! d->audio_fmt |= AFMT_S16_LE; ! d->bd_flags |= BD_F_ESS; ! d->bd_flags &= ~BD_F_MIX_MASK ; ! d->bd_flags |= BD_F_MIX_ESS688 ; ! sb_reset_dsp(io_base); ! sb_cmd(io_base, 0xc6); ! break ; } else { printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n", ess_major, ess_minor); *************** *** 747,752 **** --- 825,831 ---- static void sb_mix_init(snddev_info *d) { + u_int mixval; switch (d->bd_flags & BD_F_MIX_MASK) { case BD_F_MIX_CT1345 : /* SB 3.0 has 1345 mixer */ *************** *** 765,770 **** --- 844,863 ---- d->mix_devs = SB16_MIXER_DEVICES ; d->mix_rec_devs = SB16_RECORDING_DEVICES ; d->mix_recsrc = SOUND_MASK_MIC ; + break ; + + case BD_F_MIX_ESS688 : /* ESS688/ESS1868 mixer */ + + mixval = (u_int)sb_getmixer(d->io_base, ESS_VOLCTL); + if (mixval & 1) { + printf("ESS1868: setting master volume control register" + "(compatibility mode)\n"); + sb_setmixer(d->io_base, ESS_VOLCTL, mixval & ~1); + } + d->mix_devs = ESS_MIXER_DEVICES ; + d->mix_rec_devs = ESS_RECORDING_DEVICES ; + d->mix_recsrc = SOUND_MASK_MIC ; + break ; } sb_mixer_reset(d); } *************** *** 880,885 **** --- 973,992 ---- return sb_get_byte(io_base); } + void + ess_cont_getmixer(int io_base, u_int port, u_char *buf, int num) + { + int val; + int i; + u_long flags; + + flags = spltty(); + outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ + for (i = 0; i < num; buf++, i++) { + *buf = inb(io_base + SB_MIX_DATA); + } + splx(flags); + } /* * various utility functions for the DSP *************** *** 1016,1021 **** --- 1123,1129 ---- mask &= d->mix_rec_devs; switch (d->bd_flags & BD_F_MIX_MASK) { case BD_F_MIX_CT1345 : + case BD_F_MIX_ESS688 : if (mask == SOUND_MASK_LINE) recdev = 6 ; else if (mask == SOUND_MASK_CD) *************** *** 1108,1113 **** --- 1216,1224 ---- break; case BD_F_MIX_CT1745 : iomap = &sb16_mix ; + break; + case BD_F_MIX_ESS688 : + iomap = &ess688_mix ; break; /* XXX how about the SG NX Pro, iomap = sgnxpro_mix */ } Index: PAO/sys/i386/isa/snd/sbcard.h diff -c PAO/sys/i386/isa/snd/sbcard.h:1.1.1.3 PAO/sys/i386/isa/snd/sbcard.h:1.1.1.3.2.1 *** PAO/sys/i386/isa/snd/sbcard.h:1.1.1.3 Sat Dec 5 05:38:56 1998 --- PAO/sys/i386/isa/snd/sbcard.h Mon Dec 21 20:47:29 1998 *************** *** 2,7 **** --- 2,11 ---- * file: sbcard.h */ + /* + * $Id: sbcard.h,v 1.1.1.3.2.1 1998/12/21 11:47:29 sanpei Exp $ + */ + typedef struct _sbdev_info { } sbdev_info ; *************** *** 136,141 **** --- 140,146 ---- #define BD_F_MIX_CT1335 0x0010 /* CT1335 */ #define BD_F_MIX_CT1345 0x0020 /* CT1345 */ #define BD_F_MIX_CT1745 0x0030 /* CT1745 */ + #define BD_F_MIX_ESS688 0x0040 /* ESS688/ESS1868 mixer */ #define BD_F_SB16 0x0100 /* this is a SB16 */ #define BD_F_SB16X 0x0200 /* this is a vibra16X or clone */ *************** *** 208,213 **** --- 213,226 ---- SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \ SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE) + #define ESS_MIXER_DEVICES \ + (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | \ + SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \ + SOUND_MASK_VOLUME) + + /* XXX I don't know;-) */ + #define ESS_RECORDING_DEVICES SB16_RECORDING_DEVICES + /* * Mixer registers * *************** *** 253,258 **** --- 266,275 ---- #define SB16_IMASK_R 0x3e #define SB16_OMASK 0x3c + /* + * ESS mixer cnotrol extension registers + */ + #define ESS_VOLCTL 0x64 #ifndef __SB_MIXER_C__ mixer_tab sbpro_mix; *************** *** 264,278 **** static u_char sb16_recmasks_R[SOUND_MIXER_NRDEVICES]; #else /* __SB_MIXER_C__ defined */ mixer_tab sbpro_mix = { ! PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4), PMIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4), ! PMIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4), PMIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4), ! PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4), PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) --- 281,295 ---- static u_char sb16_recmasks_R[SOUND_MIXER_NRDEVICES]; #else /* __SB_MIXER_C__ defined */ mixer_tab sbpro_mix = { ! PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4), PMIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4), ! PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4), PMIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4), ! PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4), PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) *************** *** 280,294 **** #ifdef __SGNXPRO__ mixer_tab sgnxpro_mix = { ! PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4), ! PMIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4), ! PMIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4), ! PMIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4), ! PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4), PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), --- 297,311 ---- #ifdef __SGNXPRO__ mixer_tab sgnxpro_mix = { ! PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4), ! PMIX_ENT(SOUND_MIXER_BASS, 0x46, 0, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 0, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4), ! PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4), ! PMIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 0, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4), ! PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0), ! PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4), PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), *************** *** 312,317 **** --- 329,351 ---- PMIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 6, 2, 0x40, 6, 2), /* Obsol,Use IGAIN*/ PMIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 6, 2, 0x40, 6, 2), PMIX_ENT(SOUND_MIXER_OGAIN, 0x41, 6, 2, 0x42, 6, 2) + }; + + mixer_tab ess688_mix = { + PMIX_ENT(SOUND_MIXER_VOLUME, 0x32, 4, 4, 0x32, 0, 4), + PMIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_SYNTH, 0x36, 4, 4, 0x36, 0, 4), + PMIX_ENT(SOUND_MIXER_PCM, 0x14, 4, 4, 0x14, 0, 4), + PMIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 0, 3, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_LINE, 0x3e, 4, 4, 0x3e, 0, 4), + PMIX_ENT(SOUND_MIXER_MIC, 0x1a, 4, 4, 0x1a, 0, 4), + PMIX_ENT(SOUND_MIXER_CD, 0x38, 4, 4, 0x38, 0, 4), + PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0) }; #ifdef SM_GAMES /* Master volume is lower and PCM & FM Index: PAO/sys/i386/isa/snd/sound.c diff -c PAO/sys/i386/isa/snd/sound.c:1.1.1.3 PAO/sys/i386/isa/snd/sound.c:1.1.1.3.2.1 *** PAO/sys/i386/isa/snd/sound.c:1.1.1.3 Sat Dec 5 05:38:57 1998 --- PAO/sys/i386/isa/snd/sound.c Mon Dec 21 20:47:30 1998 *************** *** 50,55 **** --- 50,59 ---- * */ + /* + * $Id: sound.c,v 1.1.1.3.2.1 1998/12/21 11:47:30 sanpei Exp $ + */ + #include "opt_devfs.h" #include *************** *** 1242,1256 **** --- 1246,1272 ---- #include #include + #ifndef __FreeBSD_version + #include + #endif + static int + #if __FreeBSD_version > 227000 sndmmap(dev_t dev, vm_offset_t offset, int nprot) + #else + sndmmap(dev_t dev, int offset, int nprot) + #endif /* __FreeBSD_version */ { snddev_info *d = get_snddev_info(dev, NULL); DEB(printf("sndmmap d 0x%p dev 0x%04x ofs 0x%08x nprot 0x%08x\n", d, dev, offset, nprot)); + #if __FreeBSD_version > 227000 if (d == NULL || nprot & PROT_EXEC || offset < 0) + #else + if (d == NULL || nprot & PROT_EXEC) + #endif return -1 ; /* forbidden */ if (offset >= d->dbuf_out.bufsize && (nprot & PROT_WRITE) ) *************** *** 1318,1324 **** if (status_len != 0) /* only do init once */ return ; sprintf(status_buf, ! "FreeBSD Audio Driver (981022) " __DATE__ " " __TIME__ "\n" "Installed devices:\n"); for (i = 0; i < NPCM_MAX; i++) { --- 1334,1340 ---- if (status_len != 0) /* only do init once */ return ; sprintf(status_buf, ! "FreeBSD Audio Driver (981022-ESS19981221) " __DATE__ " " __TIME__ "\n" "Installed devices:\n"); for (i = 0; i < NPCM_MAX; i++) { Index: PAO/sys/i386/isa/snd/sound.h diff -c PAO/sys/i386/isa/snd/sound.h:1.1.1.2 PAO/sys/i386/isa/snd/sound.h:1.1.1.2.4.1 *** PAO/sys/i386/isa/snd/sound.h:1.1.1.2 Fri Jul 24 19:19:53 1998 --- PAO/sys/i386/isa/snd/sound.h Mon Dec 21 20:47:32 1998 *************** *** 28,33 **** --- 28,37 ---- * */ + /* + * $Id: sound.h,v 1.1.1.2.4.1 1998/12/21 11:47:32 sanpei Exp $ + */ + #ifdef KERNEL #include "pcm.h" #else Index: PAO/sys/i386/scsi/README_ncv_stg diff -c /dev/null PAO/sys/i386/scsi/README_ncv_stg:1.1.8.1 *** /dev/null Fri Dec 25 10:51:25 1998 --- PAO/sys/i386/scsi/README_ncv_stg Sun Dec 6 07:48:21 1998 *************** *** 0 **** --- 1,4 ---- + ncr53c800, tmc18c30, and scsi_low is ported from NetBSD/pc98 (based on + NetBSD 1.2), but current porting status is not good because the style of + SCSI driver of NetBSD and FreeBSD is different. + Index: PAO/sys/i386/scsi/ncr53c500/ncr53c500.c diff -c /dev/null PAO/sys/i386/scsi/ncr53c500/ncr53c500.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:26 1998 --- PAO/sys/i386/scsi/ncr53c500/ncr53c500.c Sun Dec 6 07:48:23 1998 *************** *** 0 **** --- 1,878 ---- + /* $NetBSD$ */ + /* $Id: ncr53c500.c,v 1.1.8.1 1998/12/05 22:48:23 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1995, 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifdef __NetBSD__ + #include + #endif /* __NetBSD__ */ + #ifdef __FreeBSD__ + #include + #endif /* __FreeBSD__ */ + + /*************************************************** + * DEBUG + ***************************************************/ + #ifndef DDB + #define Debugger() panic("should call debugger here (ncr53c500.c)") + #endif /* ! DDB */ + + #define NCV_DEBUG + #ifdef NCV_DEBUG + int ncv_debug; + + struct ncv_statics { + int disconnect; + int reselect; + } ncv_statics[NTARGETS]; + #endif /* NCV_DEBUG */ + + /* static */ + static void ncv_pio_read __P((struct ncv_softc *, u_int8_t *, u_int)); + static void ncv_pio_write __P((struct ncv_softc *, u_int8_t *, u_int)); + static int ncv_synch __P((struct ncv_softc *, struct targ_info *, u_int, u_int)); + static inline int ncv_reselected __P((struct ncv_softc *)); + static inline int ncv_disconnected __P((struct ncv_softc *, struct ccb *cb)); + static inline void ncv_pdma_end __P((struct ncv_softc *sc, struct targ_info *)); + static inline void ncvhw_set_count __P((struct ncv_softc *sc, int)); + static inline u_int ncvhw_get_count __P((struct ncv_softc *sc)); + static inline void ncvhw_select_register_0 __P((struct ncv_softc *)); + static inline void ncvhw_select_register_1 __P((struct ncv_softc *)); + static inline void ncvhw_fpush __P((struct ncv_softc *, u_int8_t *, int)); + + static int ncv_world_start __P((struct ncv_softc *, int)); + static void ncvhw_bus_reset __P((struct ncv_softc *)); + static void ncvhw_reset __P((struct ncv_softc *)); + static void ncvhw_init __P((struct ncv_softc *)); + static void ncvhw_synch __P((struct ncv_softc *sc, struct targ_info *)); + static int ncvhw_power __P((struct ncv_softc *, u_int)); + static int ncvhw_start_selection __P((struct ncv_softc *sc, struct ccb *)); + static void ncvhw_attention __P((struct ncv_softc *)); + + struct scsi_low_funcs ncv_funcs = + { + SC_LOW_RESET_T ncv_world_start, + SC_LOW_BUSRST_T ncvhw_bus_reset, + + SC_LOW_SELECT_T ncvhw_start_selection, + + SC_LOW_ATTEN_T ncvhw_attention, + SC_LOW_SYNCH_T ncv_synch, + + SC_LOW_INTR_T ncv_sequencer, + + NULL, /* SC_LOW_POWER_T ncvhw_power, */ + }; + + /************************************************************** + * hwfuncs + **************************************************************/ + static inline void + ncvhw_select_register_0(sc) + struct ncv_softc *sc; + { + DECLARE_IOPORT(sc); + + OUTB(cr0_cfg4, sc->sc_hw.cfg4); + } + + static inline void + ncvhw_select_register_1(sc) + struct ncv_softc *sc; + { + DECLARE_IOPORT(sc); + + OUTB(cr1_cfg5, sc->sc_hw.cfg5); + } + + static inline void + ncvhw_fpush(sc, buf, len) + struct ncv_softc *sc; + u_int8_t *buf; + int len; + { + int ptr; + DECLARE_IOPORT(sc); + + for (ptr = 0; ptr < len; ptr ++) + OUTB(cr0_sfifo, buf[ptr]); + } + + int + ncvhw_check(sc) + struct ncv_softc *sc; + { + DECLARE_IOPORT(sc); + + ncvhw_select_register_0(sc); + OUTB(cr0_cmd, CMD_NOP | CMD_DMA); + if (INB(cr0_cmd) != (CMD_NOP | CMD_DMA)) + return ENODEV; + + OUTB(cr0_cmd, CMD_NOP); + if (INB(cr0_cmd) != CMD_NOP) + return ENODEV; + + return 0; + } + + static void + ncvhw_reset(sc) + struct ncv_softc *sc; + { + DECLARE_IOPORT(sc); + + ncvhw_select_register_0(sc); + + /* dummy cmd twice */ + OUTB(cr0_cmd, CMD_NOP); + OUTB(cr0_cmd, CMD_NOP); + + /* chip reset */ + OUTB(cr0_cmd, CMD_RSTCHIP); + + /* again dummy cmd twice */ + OUTB(cr0_cmd, CMD_NOP); + OUTB(cr0_cmd, CMD_NOP); + } + + static void + ncvhw_init(sc) + struct ncv_softc *sc; + { + DECLARE_IOPORT(sc); + + ncvhw_select_register_0(sc); + OUTB(cr0_clk, sc->sc_hw.clk); + OUTB(cr0_srtout, SEL_TOUT); + OUTB(cr0_period, 0); + OUTB(cr0_offs, 0); + + OUTB(cr0_cfg1, sc->sc_hw.cfg1); + OUTB(cr0_cfg2, sc->sc_hw.cfg2); + OUTB(cr0_cfg3, sc->sc_hw.cfg3); + OUTB(cr0_tchsb, 0); + + ncvhw_select_register_1(sc); + OUTB(cr1_fstat, 0x0); + OUTB(cr1_pflag, 0x0); + OUTB(cr1_atacmd, ATACMD_ENGAGE); + + ncvhw_select_register_0(sc); + } + + static void + ncvhw_synch(sc, ti) + struct ncv_softc *sc; + struct targ_info *ti; + { + DECLARE_IOPORT(sc); + + /* start selection */ + if (ti->ti_flags & SCSI_LOW_NOPARITY) + OUTB(cr0_cfg1, sc->sc_hw.cfg1); + else + OUTB(cr0_cfg1, sc->sc_hw.cfg1 | C1_PARENB); + OUTB(cr0_period, ti->ti_synch.period); + OUTB(cr0_offs, ti->ti_synch.offset); + OUTB(cr0_cfg3, ti->ti_synch.c3img); + } + + static int + ncvhw_power(sc, flags) + struct ncv_softc *sc; + u_int flags; + { + DECLARE_IOPORT(sc); + + if (flags == SCSI_LOW_POWDOWN) + { + printf("%s power down\n", sc->sc_dvname); + ncvhw_select_register_1(sc); + OUTB(cr1_atacmd, ATACMD_POWDOWN); + } + else + { + switch (sc->sc_rstep) + { + case 0: + printf("%s resume step O\n", sc->sc_dvname); + ncvhw_select_register_1(sc); + OUTB(cr1_atacmd, ATACMD_ENGAGE); + break; + + case 1: + printf("%s resume step I\n", sc->sc_dvname); + ncvhw_reset(sc); + ncvhw_init(sc); + break; + } + } + + return 0; + } + + /************************************************************** + * scsi low interface + **************************************************************/ + static void + ncvhw_attention(sc) + struct ncv_softc *sc; + { + DECLARE_IOPORT(sc); + + OUTB(cr0_cmd, CMD_SETATN); + delay(200); + } + + static void + ncvhw_bus_reset(sc) + struct ncv_softc *sc; + { + DECLARE_IOPORT(sc); + + ncvhw_select_register_0(sc); + OUTB(cr0_cmd, CMD_FLUSH); + OUTB(cr0_cmd, CMD_RSTSCSI); + OUTB(cr0_cmd, CMD_NOP | CMD_DMA); + } + + static int + ncvhw_start_selection(sc, cb) + struct ncv_softc *sc; + struct ccb *cb; + { + struct targ_info *ti = cb->ti; + int s; + DECLARE_IOPORT(sc); + + ID_MSG_SETUP(ti, cb); + ncvhw_select_register_0(sc); + + s = splhigh(); + + if (sc->sc_disc > 0 && (INB(cr0_stat) & STAT_INT)) + { + splx(s); + return 1; + } + + ncvhw_synch(sc, ti); + OUTB(cr0_dstid, ti->ti_id); + OUTB(cr0_cmd, CMD_FLUSH); + + OUTB(cr0_sfifo, ti->ti_msgout); + + if (cb->msgoutlen) + OUTB(cr0_cmd, CMD_SELATNS); + else + { + ncvhw_fpush(sc, cb->cmd, cb->cmdlen); + OUTB(cr0_cmd, CMD_SELATN); + } + + splx(s); + + SCSI_LOW_SETUP_PHASE(PH_SELSTART); + return 0; + } + + static int + ncv_world_start(sc, fdone) + struct ncv_softc *sc; + int fdone; + { + struct targ_info *ti; + u_int8_t stat; + DECLARE_IOPORT(sc); + + if (sc->sc_flags & HW_INACTIVE) + return EBUSY; + + /* reset current nexus */ + scsi_low_reset_nexus((struct scsi_low_softc *) sc, fdone); + + /* hardware info init */ + for (ti = sc->sc_titab.tqh_first; ti; ti = ti->ti_chain.tqe_next) + { + ti->ti_state = UNIT_RDY; + ti->ti_synch.period = ti->ti_synch.offset = 0; + ti->ti_synch.c3img = sc->sc_hw.cfg3; + ti->ti_maxsynch.c3img = sc->sc_hw.cfg3; + ti->ti_maxsynch.period = sc->sc_hw.mperiod; + ti->ti_maxsynch.offset = sc->sc_hw.moffset; + + scsi_low_calcf(ti); + } + + ncvhw_reset(sc); + ncvhw_init(sc); + scsi_low_bus_reset((struct scsi_low_softc *) sc); + + ncvhw_select_register_0(sc); + INB(cr0_stat); + stat = INB(cr0_istat); + if ((stat & INTR_SBR) == 0) + return ENODEV; + delay(1000); + stat = INB(cr0_istat); + if (stat & INTR_SBR) + return ENODEV; + + #ifdef __NetBSD__ + softintr(sc->sc_mask); + #endif + return 0; + } + + static int + ncv_synch(sc, ti, period, offset) + struct ncv_softc *sc; + struct targ_info *ti; + u_int period, offset; + { + u_int hwperiod; + + hwperiod = 1000 / ((sc->sc_hw.clk == 0) ? 40 : (5 * sc->sc_hw.clk)); + + if (period < 200 / 4 && period >= 100 / 4) + ti->ti_synch.c3img |= C3_FSCSI; + else + ti->ti_synch.c3img &= ~C3_FSCSI; + + period = ((period * 40 / hwperiod) + 5) / 10; + + ti->ti_synch.period = period & 0x1f; + ti->ti_synch.offset = offset; + + return 0; + } + + /************************************************************** + * PDMA + **************************************************************/ + static inline void + ncvhw_set_count(sc, count) + struct ncv_softc *sc; + int count; + { + DECLARE_IOPORT(sc); + + OUTB(cr0_tclsb, (u_int8_t) count); + OUTB(cr0_tcmsb, (u_int8_t) (count >> NBBY)); + OUTB(cr0_tchsb, (u_int8_t) (count >> (NBBY * 2))); + } + + static inline u_int + ncvhw_get_count(sc) + struct ncv_softc *sc; + { + u_int count; + DECLARE_IOPORT(sc); + + count = (u_int) INB(cr0_tclsb); + count |= ((u_int) INB(cr0_tcmsb)) << NBBY; + count |= ((u_int) INB(cr0_tchsb)) << (NBBY * 2); + return count; + } + + static inline void + ncv_pdma_end(sc, ti) + struct ncv_softc *sc; + struct targ_info *ti; + { + int len; + DECLARE_IOPORT(sc); + + sc->sc_flags &= ~HW_PDMASTART; + if (ti->ti_phase == PH_DATA) + { + len = ncvhw_get_count(sc); + if ((sc->sc_direction & SCSI_LOW_READ) == 0) + len += (INB(cr0_sffl) & 0x1f); + + if ((u_int) len <= (u_int) sc->sc_scp.datalen) + { + sc->sc_scp.data += (sc->sc_scp.datalen - len); + sc->sc_scp.datalen = len; + if ((sc->sc_direction & SCSI_LOW_READ) && + sc->sc_tdatalen != len) + goto bad; + } + else + { + bad: + ti->ti_error |= PDMAERR; + printf("%s strange count hw 0x%x soft 0x%x tlen 0x%x\n", + sc->sc_dvname, len, sc->sc_scp.datalen, + sc->sc_tdatalen); + } + } + else + { + printf("%s data phase miss\n", sc->sc_dvname); + ti->ti_error |= PDMAERR; + } + + ncvhw_select_register_1(sc); + OUTB(cr1_fstat, 0); + ncvhw_select_register_0(sc); + } + + static void + ncv_pio_read(sc, buf, reqlen) + struct ncv_softc *sc; + u_int8_t *buf; + u_int reqlen; + { + int tout = sc->sc_wc; + register int len; + register u_int8_t fstat; + DECLARE_IOPORT(sc); + + ncvhw_select_register_1(sc); + OUTB(cr1_pflag, 0); + + ncvhw_select_register_0(sc); + ncvhw_set_count(sc, reqlen); + OUTB(cr0_cmd, CMD_TRANS | CMD_DMA); + + ncvhw_select_register_1(sc); + OUTB(cr1_fstat, FIFO_EN); + sc->sc_flags |= HW_PDMASTART; + + while (reqlen >= FIFO_F_SZ && tout > 0) + { + fstat = INB(cr1_fstat); + if (fstat & FIFO_F) + { + INSL(cr1_fdata, buf, FIFO_F_SZ / 4); + buf += FIFO_F_SZ; + reqlen -= FIFO_F_SZ; + continue; + } + else if (fstat & FIFO_BRK) + break; + + tout --; + } + + if (reqlen >= FIFO_2_SZ) + { + fstat = INB(cr1_fstat); + if (fstat & FIFO_2) + { + INSL(cr1_fdata, buf, FIFO_2_SZ / 4); + buf += FIFO_2_SZ; + reqlen -= FIFO_2_SZ; + } + } + + while (reqlen > 0 && tout > 0) + { + fstat = INB(cr1_fstat); + if ((fstat & FIFO_E) == 0) + { + *buf++ = INB(cr1_fdata); + reqlen --; + continue; + } + else if (fstat & FIFO_BRK) + break; + tout --; + } + + ncvhw_select_register_0(sc); + sc->sc_tdatalen = reqlen; + + if (tout <= 0) + printf("%s pio read timeout\n", sc->sc_dvname); + } + + static void + ncv_pio_write(sc, buf, reqlen) + struct ncv_softc *sc; + u_int8_t *buf; + u_int reqlen; + { + int tout = sc->sc_wc; + register u_int8_t fstat; + DECLARE_IOPORT(sc); + + ncvhw_select_register_1(sc); + OUTB(cr1_pflag, 0); + + ncvhw_select_register_0(sc); + ncvhw_set_count(sc, reqlen); + OUTB(cr0_cmd, CMD_TRANS | CMD_DMA); + + ncvhw_select_register_1(sc); + OUTB(cr1_fstat, FIFO_EN); + sc->sc_flags |= HW_PDMASTART; + + while (reqlen >= FIFO_F_SZ && tout > 0) + { + fstat = INB(cr1_fstat); + if (fstat & FIFO_BRK) + goto done; + + if (fstat & FIFO_E) + { + OUTSL(cr1_fdata, buf, FIFO_F_SZ / 4); + buf += FIFO_F_SZ; + reqlen -= FIFO_F_SZ; + } + else + tout --; + } + + while (reqlen > 0 && tout > 0) + { + fstat = INB(cr1_fstat); + if (fstat & FIFO_BRK) + break; + + if ((fstat & FIFO_F) == 0) /* fifo not full */ + { + OUTB(cr1_fdata, *buf++); + reqlen --; + } + else + tout --; + } + + done: + ncvhw_select_register_0(sc); + + if (tout <= 0) + printf("%s pio write timeout\n", sc->sc_dvname); + } + + /************************************************************** + * disconnect & reselect (HW low) + **************************************************************/ + static inline int + ncv_reselected(sc) + struct ncv_softc *sc; + { + struct ccb *cb; + u_int sid, imsg; + DECLARE_IOPORT(sc); + + if ((INB(cr0_sffl) & 0x1f) != 2) + { + printf("%s illegal fifo bytes\n", sc->sc_dvname); + return 0; + } + + sid = (u_int) INB(cr0_sfifo); + imsg = (u_int) INB(cr0_sfifo); + if ((imsg & 0x80) == 0) + { + printf("%s lost msg identify\n", sc->sc_dvname); + return 0; + } + + sid = ffs(sid) - 1; + cb = scsi_low_reselected((struct scsi_low_softc *) sc, sid, imsg & 0x7); + if (cb == NULL) + return 0; + + #ifdef NCV_DEBUG + ncv_statics[sid].reselect ++; + #endif + ncvhw_synch(sc, cb->ti); + OUTB(cr0_dstid, sid); + OUTB(cr0_cmd, CMD_MSGOK); + + return 1; + } + + static inline int + ncv_disconnected(sc, cb) + struct ncv_softc *sc; + struct ccb *cb; + { + DECLARE_IOPORT(sc); + + OUTB(cr0_cmd, CMD_FLUSH); + OUTB(cr0_cfg1, sc->sc_hw.cfg1); + OUTB(cr0_cmd, CMD_ENSEL); + + #ifdef NCV_DEBUG + if (sc->sc_msgphase == DISCASSERT) + ncv_statics[cb->ti->ti_id].disconnect ++; + #endif /* NCV_DEBUG */ + + scsi_low_disconnected((struct scsi_low_softc *) sc, cb); + scsi_low_start((struct scsi_low_softc *) sc); + + return 1; + } + + /************************************************************** + * SEQUENCER + **************************************************************/ + int + ncv_sequencer(sc) + struct ncv_softc *sc; + { + struct targ_info *ti; + struct ccb *cb; + int len; + u_int8_t status, ireason; + DECLARE_IOPORT(sc); + + if (sc->sc_flags & HW_INACTIVE) + return 0; + + /******************************************** + * Status + ********************************************/ + ncvhw_select_register_0(sc); + status = INB(cr0_stat); + if ((status & STAT_INT) == 0) + return 0; + + ireason = INB(cr0_istat); + if (ireason & INTR_SBR) + { + u_int8_t val; + + /* avoid power off hangup */ + val = INB(cr0_cfg1); + OUTB(cr0_cfg1, val | C1_SRR); + + /* status init */ + ti = sc->sc_titab.tqh_first; + for ( ; ti; ti = ti->ti_chain.tqe_next) + ti->ti_state = UNIT_RDY; + + printf("%s bus reset (power off ?)\n", sc->sc_dvname); + return 1; + } + + /******************************************** + * Debug section + ********************************************/ + #ifdef NCV_DEBUG + if (ncv_debug) + { + scsi_low_print((struct scsi_low_softc *) sc, NULL); + printf("%s st %x ist %x\n\n", sc->sc_dvname, + status, ireason); + if (ncv_debug > 1) + Debugger(); + } + #endif /* NCV_DEBUG */ + + /******************************************** + * Reselect or Disconnect or Nexus check + ********************************************/ + /* (I) reselect */ + if (ireason == INTR_RESELECT) + { + if ((status & PHASE_MASK) == MESSAGE_IN_PHASE) + return ncv_reselected(sc); + + return 1; + } + + /* (II) nexus */ + if ((cb = sc->sc_nexus) == NULL) + return 0; + + /******************************************** + * Internal scsi phase + ********************************************/ + ti = cb->ti; + switch (ti->ti_phase) + { + case PH_SELSTART: + sc->sc_selid = NULL; + + if ((ireason & (INTR_SBR | INTR_DIS | INTR_ILL)) || + (status & (STAT_PE | STAT_GE))) + goto abort; + + if (cb->msgoutlen == 0) + { + if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE) + break; + + SCSI_LOW_SETUP_PHASE(PH_SELECTED); + printf("%s msg identify failed\n", sc->sc_dvname); + } + else + { + if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE) + { + ti->ti_error |= FATALIO; + scsi_low_restart((struct scsi_low_softc *) sc, + "msgout error"); + return 1; + } + + SCSI_LOW_SETUP_PHASE(PH_MSGOUTEXP); + } + break; + + default: + if (sc->sc_selid) + { + scsi_low_print((struct scsi_low_softc *) sc, ti); + panic("%s internal error\n", sc->sc_dvname); + } + + if (sc->sc_flags & HW_PDMASTART) + ncv_pdma_end(sc, ti); + + abort: + if (status & (STAT_PE | STAT_GE)) + { + ti->ti_error |= PARITYERR; + scsi_low_restart((struct scsi_low_softc *) sc, + "scsi bus error"); + return 1; + } + + if (ireason & (INTR_DIS | INTR_ILL)) + { + if (ireason & INTR_ILL) + { + ti->ti_error |= FATALIO; + scsi_low_restart((struct scsi_low_softc *) sc, + "illegal cmd"); + return 1; + } + + return ncv_disconnected(sc, cb); + } + } + + /******************************************** + * Scsi phase sequencer + ********************************************/ + switch (status & PHASE_MASK) + { + case DATA_OUT_PHASE: /* data out */ + SCSI_LOW_SETUP_PHASE(PH_DATA); + sc->sc_direction = SCSI_LOW_WRITE; + ncv_pio_write(sc, sc->sc_scp.data, sc->sc_scp.datalen); + break; + + case DATA_IN_PHASE: /* data in */ + SCSI_LOW_SETUP_PHASE(PH_DATA); + sc->sc_direction = SCSI_LOW_READ; + ncv_pio_read(sc, sc->sc_scp.data, sc->sc_scp.datalen); + break; + + case COMMAND_PHASE: /* cmd out */ + SCSI_LOW_SETUP_PHASE(PH_CMD); + OUTB(cr0_cmd, CMD_FLUSH); + ncvhw_fpush(sc, cb->cmd, cb->cmdlen); + OUTB(cr0_cmd, CMD_TRANS); + break; + + case STATUS_PHASE: /* status in */ + SCSI_LOW_SETUP_PHASE(PH_COMPSEQ); + OUTB(cr0_cmd, CMD_FLUSH); + OUTB(cr0_cmd, CMD_ICCS); + break; + + default: + break; + + case MESSAGE_OUT_PHASE: /* msg out */ + OUTB(cr0_cmd, CMD_FLUSH); + + len = scsi_low_msgout((struct scsi_low_softc *) sc, ti, cb); + if (len == 0) + { + OUTB(cr0_sfifo, ti->ti_msgout); + OUTB(cr0_cmd, CMD_TRANS); + if (cb->msgoutlen == 0) + OUTB(cr0_cmd, CMD_RSTATN); + } + else if (len > 0) + { + ncvhw_fpush(sc, cb->msgout, len); + OUTB(cr0_cmd, CMD_TRANS); + OUTB(cr0_cmd, CMD_RSTATN); + } + break; + + case MESSAGE_IN_PHASE: /* msg in */ + len = INB(cr0_sffl) & 0x1f; + if (ti->ti_phase == PH_COMPSEQ) + { + if ((ireason & INTR_FC) && len == 2) + { + ti->ti_status = + INB(cr0_sfifo); + len --; + } + else + { + scsi_low_restart((struct scsi_low_softc *) sc, + "compseq error"); + + break; + } + } + else if (ireason & INTR_BS) + { + OUTB(cr0_cmd, CMD_FLUSH); + OUTB(cr0_cmd, CMD_TRANS); + break; + } + + SCSI_LOW_SETUP_PHASE(PH_MSGIN); + + if ((ireason & INTR_FC) && len == 1) + { + ti->ti_msgin[ti->ti_msginptr++] = + INB(cr0_sfifo); + scsi_low_msgin((struct scsi_low_softc *) sc, cb); + OUTB(cr0_cmd, CMD_MSGOK); + } + else + { + ti->ti_error |= MSGERR; + printf("%s st %x ist %x\n\n", sc->sc_dvname, + status, ireason); + scsi_low_restart((struct scsi_low_softc *) sc, + "hw msgin error"); + } + break; + } + + return 1; + } Index: PAO/sys/i386/scsi/ncr53c500/ncr53c500hw.h diff -c /dev/null PAO/sys/i386/scsi/ncr53c500/ncr53c500hw.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:26 1998 --- PAO/sys/i386/scsi/ncr53c500/ncr53c500hw.h Sun Dec 6 07:48:24 1998 *************** *** 0 **** --- 1,72 ---- + /* $NetBSD$ */ + /* $Id: ncr53c500hw.h,v 1.1.8.1 1998/12/05 22:48:24 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef __NCR53C500HW_H_ + #define __NCR53C500HW_H_ + + #ifndef __FreeBSD__ + #include + #endif /* __FreeBSD__ */ + + struct ncv_hw + { + /* configuration images */ + u_int8_t cfg1; + u_int8_t cfg2; + u_int8_t cfg3; + u_int8_t cfg4; + u_int8_t cfg5; + + /* synch */ + u_int8_t clk; + u_int8_t mperiod; + u_int8_t moffset; + }; + + /* dvcfg */ + #ifdef __FreeBSD__ + #define NCV_C5IMG(flags) ((flags >> 24) & 0xff) + #define NCV_CLKFACTOR(flags) ((flags>> 16) & 0x0f) + #else /* __NetBSD__ */ + #define NCV_C5IMG(flags) ((DVCFG_MAJOR(flags) >> 8) & 0xff) + #define NCV_CLKFACTOR(flags) (DVCFG_MAJOR(flags) & 0x0f) + #endif + #define NCVHWCFG_MAX10M 0x01 + #define NCVHWCFG_SCSI1 0x02 + #define NCVHWCFG_SLOW 0x04 + #define NCVHWCFG_FIFOBUG 0x08 + #ifdef __FreeBSD__ + #define NCV_SPECIAL(flags) ((flags >> 20) & 0x0f) + #else /* __NetBSD__ */ + #define NCV_SPECIAL(flags) ((DVCFG_MAJOR(flags) >> 4) & 0x0f) + #endif + #endif /* !__NCR53C500HW_H_ */ Index: PAO/sys/i386/scsi/ncr53c500/ncr53c500hw.lst diff -c /dev/null PAO/sys/i386/scsi/ncr53c500/ncr53c500hw.lst:1.1.8.1 *** /dev/null Fri Dec 25 10:51:26 1998 --- PAO/sys/i386/scsi/ncr53c500/ncr53c500hw.lst Sun Dec 6 07:48:26 1998 *************** *** 0 **** --- 1,43 ---- + /* $NetBSD$ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + static struct ncv_hw ncv_template = { + HOST_SCSI_ID, + C2_FE | C2_SCSI2, + C3_FCLK, + C4_ANE, + 0x80, + + CLK_40M_F, + + 200 / 4, + 15, + }; Index: PAO/sys/i386/scsi/ncr53c500/ncr53c500if.c diff -c /dev/null PAO/sys/i386/scsi/ncr53c500/ncr53c500if.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:27 1998 --- PAO/sys/i386/scsi/ncr53c500/ncr53c500if.c Sun Dec 6 07:48:27 1998 *************** *** 0 **** --- 1,465 ---- + /* $Id: ncr53c500if.c,v 1.1.8.1 1998/12/05 22:48:27 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1995, 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifdef __NetBSD__ + #include + #endif /* __NetBSD__ */ + #ifdef __FreeBSD__ + #include + #include "ncv.h" + #endif /* __FreeBSD__ */ + + /*************************************************** + * PARAMS + ***************************************************/ + #define NCV_MAX_CCB (2 * (NTARGETS - 1)) + + /*************************************************** + * ISA DEVICE STRUCTURE + ***************************************************/ + #ifdef __NetBSD__ + int ncvintr __P((void *)); + + struct cfdriver ncv_cd = { + NULL, "ncv", DV_DULL + }; + + struct scsi_device ncv_dev = { + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + }; + + struct scsi_adapter ncv = { + scsi_low_scsi_cmd, + scsi_low_scsi_minphys, + scsi_low_target_open, + 0, + }; + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + /*void ncvintr __P((int));*/ + + /* pccard support */ + #if NCARD > 0 + static int ncv_card_intr(struct pccard_devinfo *); + static void ncv_card_unload(struct pccard_devinfo *); + static int ncv_card_resume(struct ncv_softc *); + static int ncv_card_init(struct pccard_devinfo *); + + static struct pccard_device ncv_info = { + "ncv", + ncv_card_init, + ncv_card_unload, + ncv_card_intr, + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + /* This should also include net_imask?? */ + }; + + DATA_SET(pccarddrv_set, ncv_info); + + #ifdef SCSI_DETACH + static void ncvdetach(struct isa_device *dev); + #endif + #endif /* NCARD */ + + struct isa_driver ncvdriver = { + ncvprobe, + ncvattach, + "ncv" + }; + + struct scsi_device ncv_dev = { + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + "ncv", + 0, + {0, 0} + }; + + static struct scsi_adapter ncv = { + scsi_low_scsi_cmd, + scsi_low_scsi_minphys, + scsi_low_target_open, + 0, + ncv_adapter_info, + "ncv", + {0, 0}, + }; + u_int32_t ncv_adapter_info (int unit) + { + return 1; + } + + static struct ncv_softc *ncvdata[NNCV]; + #endif /* __FreeBSD__ */ + + /************************************************************** + * DECLARE + **************************************************************/ + extern int delaycount; + extern struct scsi_low_funcs ncv_funcs; + + /************************************************************** + * General probe attach + **************************************************************/ + #ifdef __FreeBSD__ + #if NCARD > 0 + static int + ncv_card_resume(struct ncv_softc *sc) + { + #if 0 /* XXX ncv_init */ + if (!ncv_init(sc)) + return (ENXIO); + #endif + printf("%s: resumed\n", sc->sc_dvname); + return (0); + } + + static int + ncv_card_init(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + struct ncv_softc *sc = ncvdata[unit]; + + if (NNCV <= unit) + return (ENODEV); + /* XXX -- ncv_init */ + printf("probe ncv\n"); + if (ncvprobe(&devi->isahd) == 0) + return (ENXIO); + printf("attach ncv\n"); + if (ncvattach(&devi->isahd) == 0) + return (ENXIO); + return (0); + } + + static void + ncv_card_unload(struct pccard_devinfo *devi) + { + struct ncv_softc *sc = ncvdata[devi->pd_unit]; + + printf("%s: unload\n", sc->sc_dvname); + /* scsi_low_deactivate((struct scsi_low_softc *)sc); */ + #ifdef SCSI_DETACH + ncvdetach(&devi->isahd); + #endif + } + + static int + ncv_card_intr(struct pccard_devinfo *devi) + { + + (void) ncv_sequencer(ncvdata[devi->pd_unit]); + return 1; + } + #endif /* NCARD > 0 */ + #endif /* FreeBSD */ + + static inline int + ncvhw_probe (struct ncv_softc *sc, int flags) + { + + if (NCV_CLKFACTOR(flags) > CLK_35M_F) + { + printf("%s invalid dvcfg flags\n", sc->sc_dvname); + return (-1); + } + + sc->sc_hw = ncv_template; + if (NCV_C5IMG(flags) != 0) + { + sc->sc_hw.cfg5 = NCV_C5IMG(flags); + sc->sc_hw.clk = NCV_CLKFACTOR(flags); + + if (NCV_SPECIAL(flags) & NCVHWCFG_MAX10M) + sc->sc_hw.mperiod = 100 / 4; + + /* XXX: + * RATOC scsi cards have fatal fifo asic bug. + * To avoid it, currently make sync offset 0 (async)! + */ + if (NCV_SPECIAL(flags) & NCVHWCFG_FIFOBUG) + { + sc->sc_hw.mperiod = 0; + sc->sc_hw.moffset = 0; + } + + if (NCV_SPECIAL(flags) & NCVHWCFG_SCSI1) + sc->sc_hw.cfg2 &= ~C2_SCSI2; + + if (NCV_SPECIAL(flags) & NCVHWCFG_SLOW) + sc->sc_hw.cfg1 |= C1_SLOW; + } + + /* setup configuration image 3 */ + if (sc->sc_hw.clk != CLK_40M_F && sc->sc_hw.clk <= CLK_25M_F) + sc->sc_hw.cfg3 &= ~C3_FCLK; + + #ifdef __FreeBSD__ + sc->sc_cfgflags = (flags & 0xffff); + #else + sc->sc_cfgflags = DVCFG_MINOR(flags); + #endif + sc->sc_wc = delaycount * 2000; /* 2 sec */ + sc->sc_funcs = &ncv_funcs; + + if (ncvhw_check(sc)) + return (-1); + + return (0); + } + + #ifdef __NetBSD__ + int + ncvprobe(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; + { + struct ncv_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + struct ncv_hw *hw; + DECLARE_IOPORT(sc); + + strcpy(sc->sc_dvname, sc->sc_dev.dv_xname); + if (ia->ia_iobase == IOBASEUNK || ia->ia_irq == IRQUNK) + return 0; + + bc = ia->ia_bc; + if (bus_io_map(bc, ia->ia_iobase, NCVIOSZ, &ioh)) + return 0; + sc->sc_bc = bc; + sc->sc_ioh = ioh; + sc->sc_dealyioh = ia->ia_delayioh; + + if (ncvhw_probe (sc, ia->ia_cfgflags) < 0) + { + bus_io_unmap(bc, ioh, NCVIOSZ); + return 0; + } + else if (scsi_low_attach((struct scsi_low_softc *) sc)) + return 0; + else + { + ia->ia_iosize = NCVIOSZ; + return 1; + } + } + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + int ncvprobe(struct isa_device *dev) + { + struct ncv_softc *sc; + int unit = dev->id_unit; + struct ncv_hw *hw; + char dvname[SCSI_LOW_DVNAME_LEN]; + DECLARE_IOPORT(sc); + + sprintf(dvname, "ncv%d", unit); + + if (unit >= NNCV && !dev->id_reconfig) + { + printf("%s: unit number too high\n", dvname); + return (0); + } + + if (dev->id_iobase == 0) + { + printf("%s: no ioaddr is given\n", dvname); + return (0); + } + if (dev->id_reconfig || ncvdata[unit] != NULL) + { + sc = ncvdata[unit]; + sc->sc_ioport = dev->id_iobase; + if (ncvhw_probe(sc, dev->id_flags) < 0) + return (0); + } + else + { + sc = malloc(sizeof(struct ncv_softc), M_TEMP, M_NOWAIT); + if (sc == NULL) + { + printf("%s: cannot malloc!\n", sc->sc_dvname); + return (0); + } + bzero(sc, sizeof(struct ncv_softc)); + strcpy (sc->sc_dvname, dvname); + sc->unit = unit; + ncvdata[unit] = sc; + sc->sc_ioport = dev->id_iobase; + + if (ncvhw_probe(sc, dev->id_flags) < 0) + { + free(sc, M_TEMP); + ncvdata[unit] = NULL; + return (0); + } + } + return (NCVIOSZ); + } + #endif + + int + ncvprint(aux, name) + void *aux; + char *name; + { + + if (name != NULL) + printf("%s: scsibus ", name); + return (UNCONF); + } + + #ifdef __FreeBSD__ + #define adapter_target adapter_targ + #define openings opennings + #endif + + #ifdef __FreeBSD__ + static inline void + ncv_setup_sc(register struct ncv_softc *sc) + #else + inline void ncv_setup_sc(sc) + register struct ncv_softc *sc; + #endif + { + + scsi_low_init_ccbque(NCV_MAX_CCB); + TAILQ_INIT(&sc->sc_start); + + sc->sc_link.adapter_softc = sc; + sc->sc_link.adapter_target = 7; + sc->sc_link.openings = 2; + sc->sc_link.adapter = &ncv; + sc->sc_link.device = &ncv_dev; + } + + #undef adapter_target + #undef openings + + #ifdef __NetBSD__ + void + ncvattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; + { + struct ncv_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + + printf("\n"); + sc->sc_bc = ia->ia_bc; + sc->sc_dealyioh = ia->ia_delayioh; + if (bus_io_map(sc->sc_bc, ia->ia_iobase, NCVIOSZ, &sc->sc_ioh)) + panic("%s: couldn't map io\n", sc->sc_dvname); + + ncv_setup_sc(sc); + sc->sc_mask = (1 << ia->ia_irq); + sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, + IPL_BIO, ncvintr, sc); + + config_found(self, &sc->sc_link, ncvprint); + timeout(scsi_low_timeout, sc, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz); + } + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + + #ifdef SCSI_DETACH + static void + ncvdetach(struct isa_device *dev) + { + int unit = dev->id_unit; + struct scsibus_data *scbus; + + scbus = (struct scsibus_data *)scsi_extend_get(ncvdata[unit]->sc_link.scsibus); + scsi_detachdev(scbus); + } + #endif /* SCSI_DETACH */ + + int + ncvattach(dev) + struct isa_device *dev; + { + int unit = dev->id_unit; + struct ncv_softc *sc = ncvdata[unit]; + struct scsibus_data *scbus; + + if (scsi_low_attach((struct scsi_low_softc *) sc)) + { + printf("%s: scsi low attach failed\n", sc->sc_dvname); + return (0); + } + + ncv_setup_sc(sc); + sc->sc_link.adapter_unit = unit; + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if (!scbus) + return (0); + scbus->adapter_link = &sc->sc_link; + /* + * ask the adapter what subunits are present + */ + scsi_attachdevs(scbus); + timeout(scsi_low_timeout, sc, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz); + return 1; + } + #endif /* __FreeBSD__ */ + + #ifdef __NetBSD__ + int ncvintr (arg) + void *arg; + { + return (ncv_sequencer((struct ncv_softc *)arg)); + } + #endif + + #ifdef __FreeBSD__ + void + ncvintr (unit) + int unit; + { + (void) ncv_sequencer(ncvdata[unit]); + } + #endif Index: PAO/sys/i386/scsi/ncr53c500/ncr53c500if.h diff -c /dev/null PAO/sys/i386/scsi/ncr53c500/ncr53c500if.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:27 1998 --- PAO/sys/i386/scsi/ncr53c500/ncr53c500if.h Sun Dec 6 07:48:28 1998 *************** *** 0 **** --- 1,109 ---- + /* + * Copyright (c) HONDA Naofumi, KATO Takenori, 1996. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /* $Id: ncr53c500if.h,v 1.1.8.1 1998/12/05 22:48:28 itojun Exp $ */ + + /*************************************************** + * BUS IO MAPPINGS & NCR53C500 specific inclusion + ***************************************************/ + #ifdef __NetBSD__ + #include + #include + #include + #include + #include + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + #include + #include + #include + #include + #include + + #include "apm.h" + #if NAPM > 0 + #include + #endif /* NAPM > 0 */ + + /* pccard support */ + #include "card.h" + #if NCARD > 0 + #include + #include + #include + #include + #endif /* NCARD > 0 */ + #endif /* __FreeBSD__ */ + + int ncv_sequencer __P((struct ncv_softc *sc)); + int ncvhw_check __P((struct ncv_softc *)); + + /* (II) os depend declare */ + #ifdef __NetBSD__ + int ncvprobe __P((struct device *, struct device *, void *)); + void ncvattach __P((struct device *, struct device *, void *)); + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + int ncvprobe __P((struct isa_device *dev)); + int ncvattach __P((struct isa_device *dev)); + #endif /* __FreeBSD__ */ + + #ifdef __FreeBSD__ + u_int32_t ncv_adapter_info __P((int)); + extern int dma_init_flag; + #define softintr(y) ipending |= (y) + #endif /* __FreeBSD__ */ + + + #ifdef __NetBSD__ + #define DECLARE_IOPORT(sc) \ + register bus_chipset_tag_t bc = (sc)->sc_bc; \ + register bus_io_handle_t ioh = (sc)->sc_ioh; + #define OUTB(o, val) \ + bus_io_write_1 (bc, ioh, (o), (val)) + #define OUTSL(o,b,l) \ + bus_io_write_multi_4(bc, ioh, (o), (b), (l)) + #define INB(o) \ + bus_io_read_1 (bc, ioh, (o)) + #define INSL(o,b,l) \ + bus_io_read_multi_4(bc, ioh, (o), (b), (l)) + #endif + + #ifdef __FreeBSD__ + #define DECLARE_IOPORT(sc) \ + register int ioport = (sc)->sc_ioport; + #define OUTB(o, val) \ + outb((o)+ioport, (val)) + #define OUTSL(o,b,l) \ + outsl((o)+ioport, (b), (l)) + #define INB(o) \ + inb((o)+ioport) + #define INSL(o,b,l) \ + insl((o)+ioport, (b), (l)) + #endif Index: PAO/sys/i386/scsi/ncr53c500/ncr53c500reg.h diff -c /dev/null PAO/sys/i386/scsi/ncr53c500/ncr53c500reg.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:27 1998 --- PAO/sys/i386/scsi/ncr53c500/ncr53c500reg.h Sun Dec 6 07:48:29 1998 *************** *** 0 **** --- 1,184 ---- + /* $NetBSD$ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1995, 1996 Naofumi HONDA. + * Copyright (c) 1995, 1996 Kouichi Matsuda. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _NCR53C500REG_H_ + #define _NCR53C500REG_H_ + + /* Control Register Set 0 */ + #define NCVIOSZ 0x10 + + #define cr0_tclsb 0x00 /* RW - Transfer Count Low */ + #define cr0_tcmsb 0x01 /* RW - Transfer Count Mid */ + #define cr0_sfifo 0x02 /* RW - FIFO data */ + #define cr0_cmd 0x03 /* RW - Command (2 deep) */ + #define cr0_stat 0x04 /* RO - Status */ + #define cr0_dstid 0x04 /* WO - Select/Reselect Bus ID */ + #define cr0_istat 0x05 /* RO - Interrupt */ + #define cr0_srtout 0x05 /* WO - Select/Reselect Timeout */ + #define cr0_seq 0x06 /* RO - Sequence Step */ + #define cr0_period 0x06 /* WO - Synch Transfer Period */ + #define cr0_sffl 0x07 /* RO - FIFO FLags */ + #define cr0_offs 0x07 /* WO - Synch Ofset */ + #define cr0_cfg1 0x08 /* RW - Configuration #1 */ + #define cr0_clk 0x09 /* WO - Clock Conversion Factor */ + #define cr0_tst 0x0a /* WO - Test (Chip Test Only) */ + #define cr0_cfg2 0x0b /* RW - Configuration #2 */ + #define cr0_cfg3 0x0c /* RW - Configuration #3 */ + #define cr0_cfg4 0x0d /* RW - Configuration #4 */ + #define cr0_tchsb 0x0e /* RW - Transfer Count High */ + #define cr0_fifo_bottom 0x0f /* WO - FIFO bottom */ + + /* Control Register Set 1 */ + #define cr1_jumper 0x00 /* RW - Jumper Sense Port */ + #define cr1_sram_ptr 0x01 /* RW - SRAM Address Pointer */ + #define cr1_sram_data 0x02 /* RW - SRAM Data */ + #define cr1_fdata 0x04 /* RW - PIO FIFO */ + #define cr1_fstat 0x08 /* RW - PIO Status */ + #define cr1_atacmd 0x09 /* RW - ATA Command/Status */ + #define cr1_ataerr 0x0a /* RW - ATA Features/Error */ + #define cr1_pflag 0x0b /* RW - PIO Flag Interrupt Enable */ + #define cr1_cfg5 0x0d /* RW - Configuration #5 */ + #define cr1_sig 0x0e /* RO - Signature */ + #define cr1_cfg6 0x0f /* RW - Configuration #6 */ + + /* atacmd (MPS110 ONLY) */ + #define ATACMD_POWDOWN 0x2d + #define ATACMD_ENGAGE 0x24 + + /* cfg4 */ + #define C4_ANE 0x04 + + /* cfg3 */ + #define C3_NULL 0x00 + #define C3_FCLK 0x08 /* Fast SCSI */ + #define C3_FSCSI 0x10 /* Fast Clock (>25Mhz) */ + + /* cfg2 */ + #define C2_SCSI2 0x08 /* SCSI-2 Enable */ + #define C2_FE 0x40 /* Features Enable */ + + /* cfg1 */ + #define C1_SLOW 0x80 /* Slow Cable Mode */ + #define C1_SRR 0x40 /* SCSI Reset Rep Int Dis */ + #define C1_PARENB 0x10 /* Enable Parity Check */ + + /* clk factor */ + #define CLK_40M_F 0x00 + #define CLK_25M_F 0x05 + #define CLK_30M_F 0x06 + #define CLK_35M_F 0x07 + + /* interrupt status register */ + #define INTR_SBR 0x80 /* SCSI Bus Reset */ + #define INTR_ILL 0x40 /* Illegal Command */ + #define INTR_DIS 0x20 /* Disconnect */ + #define INTR_BS 0x10 /* Bus Service */ + #define INTR_FC 0x08 /* Function Complete */ + #define INTR_RESEL 0x04 /* Reselected */ + #define INTR_SELATN 0x02 /* Select with ATN */ + #define INTR_SEL 0x01 /* Selected */ + #define INTR_RESELECT (INTR_RESEL | INTR_FC) + + /* status register */ + #define STAT_INT 0x80 /* Interrupt */ + #define STAT_GE 0x40 /* Gross Error */ + #define STAT_PE 0x20 /* Parity Error */ + #define STAT_TC 0x10 /* Terminal Count */ + + /* phase bits */ + #define IOI 0x01 + #define CDI 0x02 + #define MSGI 0x04 + + /* Information transfer phases */ + #define DATA_OUT_PHASE (0) + #define DATA_IN_PHASE (IOI) + #define COMMAND_PHASE (CDI) + #define STATUS_PHASE (CDI|IOI) + #define MESSAGE_OUT_PHASE (MSGI|CDI) + #define MESSAGE_IN_PHASE (MSGI|CDI|IOI) + + #define PHASE_MASK (MSGI|CDI|IOI) + + /* fifo status register */ + #define FIFO_SMASK 0x1e + #define FIFO_E 0x10 /* fifo empty */ + #define FIFO_B 0x00 /* there exists any */ + #define FIFO_1 0x08 /* 1/3 <= bytes < 2/3 */ + #define FIFO_2 0x04 /* 2/3 <= bytes < full */ + #define FIFO_F 0x02 /* full */ + #define FIFO_EN 0x01 /* fifo direction */ + #define FIFO_BRK 0x40 /* phase miss */ + + #define FIFO_F_SZ 128 + #define FIFO_1_SZ 44 + #define FIFO_2_SZ 84 + + /* pflags */ + #define PFR_WRITE 0x01 + + /* Commands */ + #define CMD_DMA 0x80 /* DMA Bit */ + #define CMD_NOP 0x00 /* No Operation */ + #define CMD_FLUSH 0x01 /* Flush FIFO */ + #define CMD_RSTCHIP 0x02 /* Reset Chip */ + #define CMD_RSTSCSI 0x03 /* Reset SCSI Bus */ + #define CMD_RESEL 0x40 /* Reselect Sequence */ + #define CMD_SELNATN 0x41 /* Select without ATN */ + #define CMD_SELATN 0x42 /* Select with ATN */ + #define CMD_SELATNS 0x43 /* Select with ATN & Stop */ + #define CMD_ENSEL 0x44 /* Enable (Re)Selection */ + #define CMD_DISSEL 0x45 /* Disable (Re)Selection */ + #define CMD_SELATN3 0x46 /* Select with ATN3 */ + #define CMD_RESEL3 0x47 /* Reselect3 Sequence */ + #define CMD_SNDMSG 0x20 /* Send Message */ + #define CMD_SNDSTAT 0x21 /* Send Status */ + #define CMD_SNDDATA 0x22 /* Send Data */ + #define CMD_DISCSEQ 0x23 /* Disconnect Sequence */ + #define CMD_TERMSEQ 0x24 /* Terminate Sequence */ + #define CMD_TCCS 0x25 /* Target Command Comp Seq */ + #define CMD_DISC 0x27 /* Disconnect */ + #define CMD_RECMSG 0x28 /* Receive Message */ + #define CMD_RECCMD 0x29 /* Receive Command */ + #define CMD_RECDATA 0x2a /* Receive Data */ + #define CMD_RECCSEQ 0x2b /* Receive Command Sequence */ + #define CMD_ABORT 0x04 /* Target Abort DMA */ + #define CMD_TRANS 0x10 /* Transfer Information */ + #define CMD_ICCS 0x11 /* Initiator Cmd Comp Seq */ + #define CMD_MSGOK 0x12 /* Message Accepted */ + #define CMD_TRPAD 0x18 /* Transfer Pad */ + #define CMD_SETATN 0x1a /* Set ATN */ + #define CMD_RSTATN 0x1b /* Reset ATN */ + + /* Default timeout */ + #define SEL_TOUT 0xa3 + #endif /* !_NCR53C500REG_H_ */ Index: PAO/sys/i386/scsi/ncr53c500/ncr53c500var.h diff -c /dev/null PAO/sys/i386/scsi/ncr53c500/ncr53c500var.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:27 1998 --- PAO/sys/i386/scsi/ncr53c500/ncr53c500var.h Sun Dec 6 07:48:30 1998 *************** *** 0 **** --- 1,44 ---- + /* $NetBSD$ */ + /* $Id: ncr53c500var.h,v 1.1.8.1 1998/12/05 22:48:30 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1995, 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _NCR53C500VAR_H_ + #define _NCR53C500VAR_H_ + + /* softc */ + struct ncv_softc { + SCSI_LOW_SOFTC + + struct ncv_hw sc_hw; + }; + + int ncvprint __P((void *, char *)); + #endif /* !_NCR53C500VAR_H_ */ Index: PAO/sys/i386/scsi/scsi_low/ccbque.h diff -c /dev/null PAO/sys/i386/scsi/scsi_low/ccbque.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:28 1998 --- PAO/sys/i386/scsi/scsi_low/ccbque.h Sun Dec 6 07:48:32 1998 *************** *** 0 **** --- 1,130 ---- + /* $NetBSD$ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + /* + * Common command control queue funcs. + * Written by N. Honda. + */ + + #ifndef _CCBQUE_H_ + #define _CCBQUE_H_ + + /* (I) structure and prototype */ + #define GENERIC_CCB_ASSERT(DEV, CCBTYPE) \ + TAILQ_HEAD(CCBTYPE##tab, CCBTYPE); \ + struct CCBTYPE##que { \ + struct CCBTYPE##tab CCBTYPE##tab; \ + int count; \ + int maxccb; \ + }; \ + void DEV##_init_ccbque __P((int)); \ + struct CCBTYPE *DEV##_get_ccb __P((int)); \ + void DEV##_free_ccb __P((struct CCBTYPE *)); + + /* (II) static allocated memory */ + #define GENERIC_CCB_STATIC_ALLOC(DEV, CCBTYPE) \ + static struct CCBTYPE##que CCBTYPE##que; + + /* (III) functions */ + #define GENERIC_CCB(DEV, CCBTYPE, CHAIN) \ + \ + void \ + DEV##_init_ccbque(count) \ + int count; \ + { \ + if (CCBTYPE##que.maxccb == 0) \ + TAILQ_INIT(&CCBTYPE##que.CCBTYPE##tab); \ + CCBTYPE##que.maxccb += count; \ + } \ + \ + struct CCBTYPE * \ + DEV##_get_ccb(flags) \ + int flags; \ + { \ + struct CCBTYPE *cb; \ + int s = splbio(); \ + \ + do \ + { \ + if (CCBTYPE##que.count > CCBTYPE##que.maxccb) \ + { \ + if (flags) \ + { \ + cb = NULL; \ + goto done; \ + } \ + else \ + { \ + tsleep((caddr_t) &CCBTYPE##que.count, \ + PRIBIO, "ccbwait", 0); \ + continue; \ + } \ + } \ + \ + if (cb = CCBTYPE##que.CCBTYPE##tab.tqh_first) \ + { \ + TAILQ_REMOVE(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN);\ + break; \ + } \ + else \ + { \ + if (cb = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT))\ + { \ + bzero(cb, sizeof(*cb)); \ + break; \ + } \ + else if (flags) \ + goto done; \ + \ + tsleep((caddr_t) &CCBTYPE##que.count, \ + PRIBIO, "ccbwait", 0); \ + } \ + } \ + while (1); \ + CCBTYPE##que.count ++; \ + \ + done: \ + splx(s); \ + return cb; \ + } \ + \ + void \ + DEV##_free_ccb(cb) \ + struct CCBTYPE *cb; \ + { \ + int s = splbio(); \ + \ + TAILQ_INSERT_TAIL(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN); \ + CCBTYPE##que.count --; \ + \ + if (CCBTYPE##que.count == CCBTYPE##que.maxccb) \ + wakeup ((caddr_t) &CCBTYPE##que.count); \ + splx(s); \ + } + #endif /* !_CCBQUE_H_ */ Index: PAO/sys/i386/scsi/scsi_low/scsi_dvcfg.h diff -c /dev/null PAO/sys/i386/scsi/scsi_low/scsi_dvcfg.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:28 1998 --- PAO/sys/i386/scsi/scsi_low/scsi_dvcfg.h Sun Dec 6 07:48:34 1998 *************** *** 0 **** --- 1,54 ---- + /* $NetBSD$ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _SCSI_DVCFG_H_ + #define _SCSI_DVCFG_H_ + + /* common dvcfg flags defitions for bs, ncv, stg */ + + #define DVF_SCSI_SYNC 0x01 + #define DVF_SCSI_DISC 0x02 + #define DVF_SCSI_WAIT 0x04 + #define DVF_SCSI_LINK 0x08 + #define DVF_SCSI_QTAG 0x10 + #define DVF_SCSI_SP0 0x100 + #define DVF_SCSI_NOPARITY 0x200 + #define DVF_SCSI_SAVESP 0x400 + #define DVF_SCSI_SP1 0x800 + #define DVF_SCSI_PERIOD(XXX) (((XXX) >> 24) & 0xff) + #define DVF_SCSI_OFFSET(XXX) (((XXX) >> 16) & 0xff) + #define DVF_SCSI_SYNCMASK 0xffff0000 + + #define DVF_SCSI_DEFCFG (DVF_SCSI_SYNC | DVF_SCSI_NOPARITY | DVF_SCSI_SYNCMASK) + + #define DVF_SCSI_BITS "\020\13fssp\12noparity\11nosat\005qtag\004cmdlnk\003wait\002disc\001sync" + + #endif /* !_SCSI_DVCFG_H_ */ Index: PAO/sys/i386/scsi/scsi_low/scsi_low.c diff -c /dev/null PAO/sys/i386/scsi/scsi_low/scsi_low.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:28 1998 --- PAO/sys/i386/scsi/scsi_low/scsi_low.c Sun Dec 6 07:48:35 1998 *************** *** 0 **** --- 1,1225 ---- + /* $NetBSD$ */ + /* $Id: scsi_low.c,v 1.1.8.1 1998/12/05 22:48:35 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1995, 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifdef __NetBSD__ + #include + #endif /* __NetBSD__ */ + #ifdef __FreeBSD__ + #include + #endif /* __FreeBSD__ */ + + /************************************************************** + * power control + **************************************************************/ + #ifdef SCSI_LOW_POWFUNC + static void scsi_low_recover __P((void *)); + + static void + scsi_low_recover(arg) + void *arg; + { + struct scsi_low_softc *sc = arg; + int s = splbio(); + + switch (sc->sc_rstep) + { + case 0: + sc->sc_rstep = 1; + (*sc->sc_funcs->scsi_low_power) (sc, SCSI_LOW_ENGAGE); + timeout(scsi_low_recover, sc, 1); + break; + + case 1: + sc->sc_flags &= ~HW_RESUME; + scsi_low_start(sc); + break; + } + + splx(s); + } + #endif /* SCSI_LOW_POWFUNC */ + + int + scsi_low_reset(sc, flags) + struct scsi_low_softc *sc; + u_int flags; + { + + #ifdef SCSI_LOW_POWFUNC + untimeout(scsi_low_recover, sc); + sc->sc_flags &= ~(HW_POWDOWN | HW_RESUME); + + sc->sc_oc = 1; + sc->sc_powc = SCSI_LOW_POWDOWN_TC; + #endif /* SCSI_LOW_POWFUNC */ + + return ((*sc->sc_funcs->scsi_low_reset)(sc, flags)); + } + + /************************************************************** + * allocate targ_info + **************************************************************/ + struct targ_info * + scsi_low_alloc_ti(sc, targ) + struct scsi_low_softc *sc; + int targ; + { + struct targ_info *ti; + + if (sc->sc_titab.tqh_first == NULL) + TAILQ_INIT(&sc->sc_titab); + + ti = malloc(sizeof(struct targ_info), M_DEVBUF, M_NOWAIT); + if (ti == NULL) + panic("%s short of memory\n", sc->sc_dvname); + + bzero(ti, sizeof(struct targ_info)); + ti->ti_id = targ; + ti->ti_sc = sc; + ti->ti_quirks = 0; + #ifdef SDEV_NOPARITY + ti->ti_quirks |= SDEV_NOPARITY; + #endif + #ifdef SDEV_NODISC + ti->ti_quirks |= SDEV_NODISC; + #endif + ti->ti_cfgflags = 0xffff0000 | SCSI_LOW_SYNC; + + sc->sc_ti[targ] = ti; + TAILQ_INSERT_TAIL(&sc->sc_titab, ti, ti_chain); + + return ti; + } + + void + scsi_low_free_ti(sc) + struct scsi_low_softc *sc; + { + struct targ_info *ti, *tib; + + for (ti = sc->sc_titab.tqh_first; ti; ti = tib) + { + tib = ti->ti_chain.tqe_next; + free(ti, M_DEVBUF); + } + } + + int + scsi_low_attach(sc) + struct scsi_low_softc *sc; + { + int i; + + for (i = 0; i < NTARGETS; i ++) + scsi_low_alloc_ti((struct scsi_low_softc *) sc, i); + + if (scsi_low_reset(sc, 0)) + { + scsi_low_free_ti((struct scsi_low_softc *) sc); + return EINVAL; + } + + return 0; + } + + /************************************************************** + * timeout + **************************************************************/ + void + scsi_low_timeout(arg) + void *arg; + { + struct scsi_low_softc *sc = arg; + struct ccb *cb; + int reset, s = splbio(); + + /* check */ + reset = 0; + if (cb = sc->sc_nexus) + { + if ((cb->tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL) < 0) + { + cb->ti->ti_error |= TIMEOUTIO; + reset = 1; + } + } + else if (sc->sc_disc > 0) + { + struct targ_info *ti; + + for (ti = sc->sc_titab.tqh_first; ti; ti = ti->ti_chain.tqe_next) + { + if ((cb = ti->ti_disccb) == NULL) + continue; + + if ((cb->tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL) < 0) + { + ti->ti_error |= TIMEOUTIO; + reset = 1; + } + } + } + else + { + cb = sc->sc_start.tqh_first; + if (cb) + { + if ((cb->tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL) < 0) + { + cb->ti->ti_error |= TIMEOUTIO; + reset = 1; + } + } + #ifdef SCSI_LOW_POWFUNC + else + { + if (sc->sc_oc == 0) + { + sc->sc_powc --; + if (sc->sc_powc < 0) + { + sc->sc_powc = SCSI_LOW_POWDOWN_TC; + + if ((sc->sc_flags & (HW_POWDOWN | HW_RESUME)) == 0) + { + sc->sc_flags |= HW_POWDOWN; + if (sc->sc_funcs->scsi_low_power) + (*sc->sc_funcs->scsi_low_power) (sc, SCSI_LOW_POWDOWN); + } + } + } + else + { + sc->sc_powc = SCSI_LOW_POWDOWN_TC; + sc->sc_oc = 0; + } + } + #endif /* SCSI_LOW_POWFUNC */ + } + + /* try to recover */ + if (reset) + { + struct targ_info *ti; + + printf("%s: scsi bus hangup\n", sc->sc_dvname); + for (ti = sc->sc_titab.tqh_first; ti; ti = ti->ti_chain.tqe_next) + scsi_low_print(sc, ti); + + scsi_low_reset (sc, 1); + scsi_low_start(sc); + } + + timeout(scsi_low_timeout, sc, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz); + splx(s); + } + + /************************************************************** + * CCB + **************************************************************/ + GENERIC_CCB_STATIC_ALLOC(scsi_low, ccb) + GENERIC_CCB(scsi_low, ccb, ccb_chain) + + /************************************************************** + * SCSI INTERFACE + **************************************************************/ + #define SCSI_LOW_MINPHYS 0x10000 + + void + scsi_low_scsi_minphys(bp) + struct buf *bp; + { + + if (bp->b_bcount > SCSI_LOW_MINPHYS) + bp->b_bcount = SCSI_LOW_MINPHYS; + minphys(bp); + } + + int + scsi_low_scsi_cmd(xs) + struct scsi_xfer *xs; + { + struct scsi_low_softc *sc = xs->sc_link->adapter_softc; + struct targ_info *ti; + struct ccb *cb; + int s; + + if (sc->sc_cfgflags & CFG_NOATTEN) + { + if (xs->sc_link->lun > 0) + { + xs->error = XS_DRIVER_STUFFUP; + return COMPLETE; + } + } + + if ((cb = scsi_low_get_ccb(xs->flags & SCSI_NOSLEEP)) == NULL) + return TRY_AGAIN_LATER; + + cb->ti = ti = sc->sc_ti[xs->sc_link->target]; + + cb->xs = xs; + cb->lun = xs->sc_link->lun; + cb->rcnt = 0; + + s = splbio(); + + TAILQ_INSERT_TAIL(&sc->sc_start, cb, ccb_chain); + if (sc->sc_nexus == NULL) + scsi_low_start(sc); + + if (xs->flags & SCSI_POLL) + { + int timeo = xs->timeout; + + while ((xs->flags & ITSDONE) == 0 && timeo -- > 0) + { + delay(1000); /* 1 ms */ + (*sc->sc_funcs->scsi_low_intr) (sc); + } + + if (timeo <= 0 && (xs->flags & ITSDONE) == 0) + { + scsi_low_reset(sc, 0); + ti->ti_error |= (TIMEOUTIO | ABORTIO); + scsi_low_done(sc, cb); + SCSI_LOW_SETUP_PHASE(PH_NULL); + sc->sc_nexus = NULL; + } + + splx(s); + return COMPLETE; + } + + splx(s); + return SUCCESSFULLY_QUEUED; + } + + /************************************************************** + * Start & Done + **************************************************************/ + static struct scsi_test_unit_ready unit_ready_cmd; + static struct scsi_start_stop ss_cmd = { START_STOP, 0, {0,0,}, SSS_START, }; + + #define IO_BLOCK_CHECK(sc) \ + { \ + if (sc->sc_flags & HW_INACTIVE) \ + return; \ + } + + void + scsi_low_start(sc) + struct scsi_low_softc *sc; + { + struct scsi_xfer *xs; + struct targ_info *ti; + struct ccb *cb; + int i, wc; + + IO_BLOCK_CHECK(sc) + + #ifdef SCSI_LOW_POWFUNC + sc->sc_oc ++; + + if (sc->sc_flags & (HW_POWDOWN | HW_RESUME)) + { + if (sc->sc_flags & HW_RESUME) + return; + + sc->sc_flags &= ~HW_POWDOWN; + if (sc->sc_funcs->scsi_low_power) + { + sc->sc_flags |= HW_RESUME; + sc->sc_rstep = 0; + (*sc->sc_funcs->scsi_low_power) (sc, SCSI_LOW_ENGAGE); + + timeout(scsi_low_recover, sc, 1); + return; + } + } + #endif /* SCSI_LOW_POWFUNC */ + + /* setup nexus */ + if ((cb = sc->sc_nexus) == NULL) + { + for (cb = sc->sc_start.tqh_first; cb; cb = cb->ccb_chain.tqe_next) + if (cb->ti->ti_phase == PH_NULL) + break; + + if (cb == NULL) + return; + + if (cb != sc->sc_start.tqh_first) + { + TAILQ_REMOVE(&sc->sc_start, cb, ccb_chain); + TAILQ_INSERT_HEAD(&sc->sc_start, cb, ccb_chain); + } + + sc->sc_nexus = cb; + } + + xs = cb->xs; + ti = cb->ti; + cb->msgoutlen = 0; + ti->ti_msginptr = 0; + ti->ti_error = 0; + SCSI_LOW_SETUP_MSGPHASE(NOMSG); + + if (ti->ti_tflags & TARG_CA) + { + /* XXX: + * ahc and ncr(PCI) drivers forget to init the sense_data + * buffer! send-pr! + */ + bzero(&sc->sc_sense, sizeof(sc->sc_sense)); + #ifdef __NetBSD__ + sc->sc_sense_cmd.opcode = REQUEST_SENSE; + #else + sc->sc_sense_cmd.op_code = REQUEST_SENSE; + #endif + sc->sc_sense_cmd.byte2 = (cb->lun << 5); + sc->sc_sense_cmd.length = sizeof(sc->sc_sense); + cb->cmd = (u_int8_t *) &sc->sc_sense_cmd; + cb->cmdlen = sizeof(sc->sc_sense_cmd); + cb->data = (u_int8_t *) &sc->sc_sense; + cb->datalen = sizeof(sc->sc_sense); + cb->tcmax = 15; + } + else switch(ti->ti_state) + { + case UNIT_RDY: + cb->cmd = (u_int8_t *) &unit_ready_cmd; + cb->cmdlen = sizeof(unit_ready_cmd); + cb->datalen = 0; + cb->tcmax = 15; + break; + + case UNIT_START: + cb->cmd = (u_int8_t *) &ss_cmd; + cb->cmdlen = sizeof(ss_cmd); + cb->datalen = 0; + cb->tcmax = 30; + break; + + case UNIT_SYNCH: + ti->ti_state = UNIT_OK; + ti->ti_tflags |= TARG_SYNCH_PEND; + + case UNIT_OK: + if ((ti->ti_tflags & TARG_SYNCH_PEND) && + (xs->flags & SCSI_POLL) == 0) + { + ti->ti_tflags &= ~TARG_SYNCH_PEND; + if (ti->ti_maxsynch.offset > 0) + { + ti->ti_state = UNIT_SYNCH; + cb->msgout[0] = MSG_EXTEND; + cb->msgout[1] = MSG_EXTEND_SYNCHLEN; + cb->msgout[2] = MSG_EXTEND_SYNCHCODE; + cb->msgout[3] = ti->ti_maxsynch.period; + cb->msgout[4] = ti->ti_maxsynch.offset; + cb->msgoutlen = MSG_EXTEND_SYNCHLEN + 2; + cb->cmd = (u_int8_t *) &unit_ready_cmd; + cb->cmdlen = sizeof(unit_ready_cmd); + cb->datalen = 0; + cb->tcmax = 15; + break; + } + } + + cb->cmd = (u_int8_t *) xs->cmd; + cb->cmdlen = xs->cmdlen; + cb->data = xs->data; + cb->datalen = xs->datalen; + cb->tcmax = (xs->timeout >> 10); + break; + } + + /* timeout */ + if (cb->tcmax < SCSI_LOW_MIN_TOUT) + cb->tcmax = SCSI_LOW_MIN_TOUT; + cb->tc = cb->tcmax; + + /* setup data pointer */ + sc->sc_scp.data = ti->ti_sscp.data = cb->data; + sc->sc_scp.datalen = ti->ti_sscp.datalen = cb->datalen; + + if (((*sc->sc_funcs->scsi_low_start_bus)(sc, cb)) == 0) + { + sc->sc_selid = ti; + } + else + { + sc->sc_selid = NULL; + sc->sc_nexus = NULL; + SCSI_LOW_SETUP_PHASE(PH_NULL); + } + } + + int + scsi_low_done(arg, cb) + void *arg; + struct ccb *cb; + { + struct scsi_low_softc *sc = arg; + struct scsi_xfer *xs = cb->xs; + struct targ_info *ti = cb->ti; + + if (ti->ti_error == 0) + { + if (ti->ti_tflags & TARG_CA) + { + xs->sense = sc->sc_sense; + xs->error = XS_SENSE; + cb->rcnt = MAXRETRY; + } + else switch (ti->ti_status) + { + case ST_GOOD: + if (sc->sc_scp.datalen != 0 && xs->bp) + { + ti->ti_error |= PDMAERR; + xs->error = XS_DRIVER_STUFFUP; + } + else + xs->error = XS_NOERROR; + break; + + case ST_CHKCOND: + case ST_MET: + ti->ti_tflags |= TARG_CA; + return 1; + + case ST_BUSY: + ti->ti_error |= ERRBUSY; + xs->error = XS_BUSY; + break; + + default: + ti->ti_error |= FATALIO; + xs->error = XS_DRIVER_STUFFUP; + break; + } + + if (ti->ti_state < UNIT_OK) + { + check: + ti->ti_tflags &= ~TARG_CA; + ti->ti_state ++; + cb->rcnt = 0; + return 1; + } + } + else + { + if (ti->ti_phase == PH_SELSTART) + { + xs->error = XS_TIMEOUT; + if (ti->ti_state == UNIT_RDY) + ti->ti_error |= ABORTIO; + } + else if (ti->ti_state < UNIT_OK) + { + goto check; + } + else + xs->error = XS_DRIVER_STUFFUP; + + if (ti->ti_error & ABORTIO) + cb->rcnt = MAXRETRY; + } + + /* internal retry check */ + if (xs->error == XS_NOERROR) + { + xs->resid = 0; + ti->ti_tflags &= ~TARG_CA; + } + else + { + if (xs->bp && xs->error != XS_SENSE) + { + printf("%s: buffered io error\n", sc->sc_dvname); + scsi_low_print(sc, ti); + } + + ti->ti_tflags &= ~TARG_CA; + if (cb->rcnt ++ < MAXRETRY) + return 1; + } + + xs->flags |= ITSDONE; + scsi_done(xs); + + /* free our target */ + TAILQ_REMOVE(&sc->sc_start, cb, ccb_chain); + scsi_low_free_ccb(cb); + return 0; + } + + /************************************************************** + * Reset + **************************************************************/ + void + scsi_low_reset_nexus(sc, fdone) + struct scsi_low_softc *sc; + int fdone; + { + struct targ_info *ti; + struct ccb *cb; + + /* current nexus */ + if (fdone && (cb = sc->sc_nexus) && cb->rcnt ++ >= MAXRETRY) + { + cb->ti->ti_error |= FATALIO; + scsi_low_done(sc, cb); + } + + /* disconnected nexus */ + for (ti = sc->sc_titab.tqh_first; ti; ti = ti->ti_chain.tqe_next) + { + if (ti->ti_phase == PH_DISC) + { + cb = ti->ti_disccb; + ti->ti_disccb = NULL; + TAILQ_INSERT_HEAD(&sc->sc_start, cb, ccb_chain); + if (fdone && cb->rcnt ++ >= MAXRETRY) + { + ti->ti_error |= FATALIO; + scsi_low_done(sc, cb); + } + } + + SCSI_LOW_SETUP_PHASE(PH_NULL); + ti->ti_tflags &= ~TARG_CA; + } + + sc->sc_flags &= ~HW_PDMASTART; + SCSI_LOW_SETUP_MSGPHASE(NOMSG); + sc->sc_disc = 0; + sc->sc_selid = NULL; + sc->sc_nexus = NULL; + } + + /* misc */ + static int tw_pos; + static char tw_chars[] = "|/-\\"; + + void + scsi_low_twiddle_wait(void) + { + + #ifdef __NetBSD__ + cnputc('\b'); + cnputc(tw_chars[tw_pos++]); + #endif + tw_pos %= (sizeof(tw_chars) - 1); + delay(TWIDDLEWAIT); + } + + void + scsi_low_bus_reset(sc) + struct scsi_low_softc *sc; + { + int i; + + (*sc->sc_funcs->scsi_low_bus_reset) (sc); + + printf("%s: try to reset scsi bus ", sc->sc_dvname); + for (i = 0; i <= SCSI2_RESET_DELAY / TWIDDLEWAIT ; i++) + scsi_low_twiddle_wait(); + #ifdef __NetBSD__ + cnputc('\b'); + #endif + printf("\n"); + } + + int + scsi_low_restart(sc, s) + struct scsi_low_softc *sc; + u_char *s; + { + int error; + + if (s) + printf("%s: scsi bus restart. reason: %s\n", + sc->sc_dvname, s); + + if (error = scsi_low_reset(sc, 0)) + return error; + + scsi_low_start(sc); + return 0; + } + + /************************************************************** + * disconnect and reselect + **************************************************************/ + struct ccb * + scsi_low_reselected(sc, targ, lun) + struct scsi_low_softc *sc; + u_int targ; + u_int lun; + { + struct targ_info *ti; + struct ccb *cb; + u_char *s; + + /* check collision */ + if ((ti = sc->sc_selid) != NULL) + { + SCSI_LOW_SETUP_PHASE(PH_NULL); + sc->sc_selid = NULL; + } + + if (targ >= NTARGETS || targ == HOST_SCSI_ID) + { + s = "scsi id illegal"; + goto bad; + } + + ti = sc->sc_ti[targ]; + if (ti->ti_phase != PH_DISC) + { + s = "phase mismatch"; + goto bad; + } + + cb = ti->ti_disccb; + if (lun != SCSI_LOW_LUNUNK && cb->lun != lun) + { + s = "lun mismatch"; + goto bad; + } + + /* clear the disconnect state */ + ti->ti_disccb = NULL; + SCSI_LOW_SETUP_PHASE(PH_RESEL); + sc->sc_disc --; + + /* setup the nexus */ + TAILQ_INSERT_HEAD(&sc->sc_start, cb, ccb_chain); + sc->sc_nexus = cb; + + /* recover a saved data pointer */ + sc->sc_scp = ti->ti_sscp; + return cb; + + bad: + printf("%s: reselect %s (targ:lun) = (%x:%x)\n", + sc->sc_dvname, s, targ, lun); + return 0; + } + + int + scsi_low_disconnected(sc, cb) + struct scsi_low_softc *sc; + struct ccb *cb; + { + struct targ_info *ti = cb->ti; + + /* check phase completion */ + switch (sc->sc_msgphase) + { + case DISCASSERT: + TAILQ_REMOVE(&sc->sc_start, cb, ccb_chain); + ti->ti_disccb = cb; + SCSI_LOW_SETUP_PHASE(PH_DISC); + sc->sc_disc ++; + break; + + case NOMSG: + ti->ti_error |= FATALIO; + + case CMDCOMPLETE: + scsi_low_done(sc, cb); + SCSI_LOW_SETUP_PHASE(PH_NULL); + break; + } + + SCSI_LOW_SETUP_MSGPHASE(NOMSG); + sc->sc_nexus = NULL; + return 1; + } + + /************************************************************** + * msgout + **************************************************************/ + int + scsi_low_msgout(sc, ti, cb) + struct scsi_low_softc *sc; + struct targ_info *ti; + struct ccb *cb; + { + int len; + + if (ti->ti_phase == PH_MSGOUT) + { + if (cb->rcnt ++ < MAXRETRY) + cb->msgoutlen = ti->ti_omsgoutlen; + } + else + SCSI_LOW_SETUP_PHASE(PH_MSGOUT); + + if (ti->ti_ophase == PH_SELECTED) + { + if (cb->msgoutlen) + { + (*sc->sc_funcs->scsi_low_attention)(sc); + SCSI_LOW_SETUP_PHASE(PH_MSGOUTEXP) + } + + ID_MSG_SETUP(ti, cb); + return 0; + } + + if (cb->msgoutlen == 0) + { + cb->msgout[0] = MSG_REJECT; + len = 1; + } + else + { + ti->ti_msgout = cb->msgout[0]; + ti->ti_emsgout = cb->msgout[2]; + len = cb->msgoutlen; + } + + ti->ti_omsgoutlen = cb->msgoutlen; + cb->msgoutlen = 0; + + return len; + } + + /************************************************************** + * msgin + **************************************************************/ + static void scsi_low_msgin_ext __P((struct targ_info *, struct ccb *)); + static void scsi_low_msgin_error __P((struct targ_info *, u_int, u_int8_t)); + static int scsi_low_synch __P((struct targ_info *)); + static void scsi_low_msg_reject __P((struct targ_info *)); + + #define PERIOD (ti->ti_msgin[3]) + #define OFFSET (ti->ti_msgin[4]) + + static int + scsi_low_synch(ti) + struct targ_info *ti; + { + struct scsi_low_softc *sc = ti->ti_sc; + u_int period = 0, offset = 0, speed; + u_char *s; + + if (PERIOD >= ti->ti_maxsynch.period && + OFFSET <= ti->ti_maxsynch.offset) + { + if (offset = OFFSET) + period = PERIOD; + s = offset ? "synchronous" : "async"; + } + else + s = "illegal"; + + (*sc->sc_funcs->scsi_low_synch) (sc, ti, period, offset); + + printf("%s(%d:0): <%s> offset %d period 0x%x chip(0x%x) ", + sc->sc_dvname, ti->ti_id, s, offset, period, + (u_int) ti->ti_synch.period); + + if (period) + { + speed = 2500 / period; + printf("%d.%d M/s", speed / 10, speed % 10); + } + + printf("\n"); + return 0; + } + + #define MSGWAIT(cnt) {if(ti->ti_msginptr < (cnt)) return;} + + static void + scsi_low_msgin_ext(ti, cb) + struct targ_info *ti; + struct ccb *cb; + { + struct scsi_low_softc *sc = ti->ti_sc; + int count; + u_int reqlen; + u_int32_t *ptr; + + MSGWAIT(2); + + reqlen = ti->ti_msgin[1]; + if (reqlen == 0) + reqlen = 256; + + if (ti->ti_msginptr >= MAXMSGLEN) + ti->ti_msginptr = 3; /* XXX */ + + MSGWAIT(reqlen + 2); + + switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2])) + { + case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE): + ptr = (u_int32_t *)(&ti->ti_msgin[3]); + count = (int) htonl((long) (*ptr)); + + if(sc->sc_scp.datalen - count >= 0 && + sc->sc_scp.datalen - count <= cb->datalen) + { + sc->sc_scp.datalen -= count; + sc->sc_scp.data += count; + } + else + scsi_low_msgin_error(ti, 7, MSG_REJECT); + break; + + case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE): + if (cb->ti->ti_state == UNIT_SYNCH) + scsi_low_synch(ti); + else + { + (*sc->sc_funcs->scsi_low_attention)(sc); + + cb->msgout[0] = MSG_EXTEND; + cb->msgout[1] = MSG_EXTEND_SYNCHLEN; + cb->msgout[2] = MSG_EXTEND_SYNCHCODE; + cb->msgout[3] = 0; + cb->msgout[4] = 0; + cb->msgoutlen = MSG_EXTEND_SYNCHLEN + 2; + } + break; + + case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE): + (*sc->sc_funcs->scsi_low_attention)(sc); + + cb->msgout[0] = MSG_EXTEND; + cb->msgout[1] = MSG_EXTEND_WIDELEN; + cb->msgout[2] = MSG_EXTEND_WIDECODE; + cb->msgout[3] = 0; + cb->msgoutlen = MSG_EXTEND_WIDELEN + 2; + break; + + default: + scsi_low_msgin_error(ti, 0, MSG_REJECT); + break; + } + + ti->ti_msginptr = 0; + return; + } + + static void + scsi_low_msg_reject(ti) + struct targ_info *ti; + { + struct scsi_low_softc *sc = ti->ti_sc; + struct ccb *cb; + char *s = "unexpected msg reject"; + + if ((cb = sc->sc_nexus) == NULL) + return; + + switch (ti->ti_ophase) + { + case PH_CMD: + s = "cmd rejected"; + break; + + case PH_MSGOUT: + if (ti->ti_msgout & 0x80) + { + s = "identify msg rejected"; + } + else if (ti->ti_msgout == MSG_EXTEND) + { + switch (ti->ti_emsgout) + { + case MSG_EXTEND_SYNCHCODE: + s = "synchrnous msg rejected"; + break; + + default: + break; + } + } + break; + + default: + break; + } + + printf("%s: %s\n", sc->sc_dvname, s); + ti->ti_error |= MSGERR; + } + + static void + scsi_low_msgin_error(ti, count, msg) + struct targ_info *ti; + u_int count; + u_int8_t msg; + { + struct scsi_low_softc *sc = ti->ti_sc; + struct ccb *cb; + int n; + + MSGWAIT(count); + + printf("%s: illegal msg", sc->sc_dvname); + for (n = 0; n < ti->ti_msginptr; n ++) + printf("[0x%x] ", (u_int) ti->ti_msgin[n]); + printf("\n"); + + ti->ti_msginptr = 0; + if ((cb = sc->sc_nexus) == NULL) + return; + + (*sc->sc_funcs->scsi_low_attention) (sc); + + cb->msgoutlen = 1; + cb->msgout[0] = msg; + } + + void + scsi_low_msgin(sc, cb) + struct scsi_low_softc *sc; + struct ccb *cb; + { + struct targ_info *ti = cb->ti; + + switch (ti->ti_msgin[0]) + { + case MSG_SAVESP: + ti->ti_sscp = sc->sc_scp; + break; + + case MSG_RESTORESP: + sc->sc_scp = ti->ti_sscp; + break; + + case MSG_REJECT: + scsi_low_msg_reject(ti); + break; + + case MSG_NOOP: + break; + + case MSG_I_ERROR:/* all I -> T : nothing to do*/ + case MSG_ABORT: + case MSG_PARITY: + case MSG_RESET: + case 0xe: + case 0xf: + scsi_low_msgin_error(ti, 1, MSG_REJECT); + goto resume; + + case MSG_EXTEND: + scsi_low_msgin_ext(ti, cb); + goto resume; + + case 0xd: + scsi_low_msgin_error(ti, 2, MSG_REJECT); + goto resume; + + case MSG_DISCON: + SCSI_LOW_SETUP_MSGPHASE(DISCASSERT); + break; + + case MSG_COMP: + SCSI_LOW_SETUP_MSGPHASE(CMDCOMPLETE); + break; + + case MSG_LCOMP: + case MSG_LCOMP_F: + scsi_low_msgin_error(ti, 1, MSG_REJECT); + goto resume; + + default: + if (ti->ti_msgin[0] & 0x80) + { + if ((ti->ti_msgin[0] & 0x07) != cb->lun) + { + printf("%s: lun error\n", sc->sc_dvname); + scsi_low_msgin_error(ti, 1, MSG_ABORT); + } + break; + } + else if (ti->ti_msgin[0] < 0x20) + scsi_low_msgin_error(ti, 1, MSG_REJECT); + else if (ti->ti_msgin[0] < 0x30) + scsi_low_msgin_error(ti, 2, MSG_REJECT); + else + scsi_low_msgin_error(ti, 1, MSG_REJECT); + goto resume; + } + + ti->ti_msginptr = 0; + + resume: + return; + } + + #define MAXOFFSET 0x10 + + void + scsi_low_calcf(ti) + struct targ_info *ti; + { + u_int period; + u_int8_t offset; + struct scsi_low_softc *sc = ti->ti_sc; + + ti->ti_flags &= ~SCSI_LOW_DISC; + #ifdef SDEV_NODISC + if ((sc->sc_cfgflags & CFG_NODISC) == 0 && + (ti->ti_quirks & SDEV_NODISC) == 0 && + (ti->ti_cfgflags & SCSI_LOW_DISC) != 0) + ti->ti_flags |= SCSI_LOW_DISC; + #endif + + ti->ti_flags |= SCSI_LOW_NOPARITY; + #ifdef SDEV_NOPARITY + if ((sc->sc_cfgflags & CFG_NOPARITY) == 0 && + (ti->ti_quirks & SDEV_NOPARITY) == 0 && + (ti->ti_cfgflags & SCSI_LOW_NOPARITY) == 0) + ti->ti_flags &= ~SCSI_LOW_NOPARITY; + #endif + + ti->ti_flags &= ~SCSI_LOW_SYNC; + if ((ti->ti_cfgflags & SCSI_LOW_SYNC) && + (sc->sc_cfgflags & CFG_ASYNC) == 0) + { + offset = SCSI_LOW_OFFSET(ti->ti_cfgflags); + if (offset > ti->ti_maxsynch.offset) + offset = ti->ti_maxsynch.offset; + ti->ti_flags |= SCSI_LOW_SYNC; + } + else + offset = 0; + + if (offset > 0) + { + period = SCSI_LOW_PERIOD(ti->ti_cfgflags); + if (period > 100) + period = 100; /* MAX 10M FAST SCSI2 */ + if (period) + period = 2500 / period; + if (period < ti->ti_maxsynch.period) + period = ti->ti_maxsynch.period; + } + else + period = 0; + + ti->ti_maxsynch.offset = offset; + ti->ti_maxsynch.period = period; + } + + int + scsi_low_target_open(link, cf) + struct scsi_link *link; + struct cfdata *cf; + { + u_int target = link->target; + u_int lun = link->lun; + struct scsi_low_softc *sc; + struct targ_info *ti; + u_int quirks, flags; + + sc = (struct scsi_low_softc *) link->adapter_softc; + ti = sc->sc_ti[target]; + ti->ti_quirks = (u_int) link->quirks; + ti->ti_cfgflags = cf->cf_flags; + if (ti->ti_state > UNIT_SYNCH) + ti->ti_state = UNIT_SYNCH; + + scsi_low_calcf(ti); + + printf("%s(%d:%d): max period(0x%x) max offset(%d) flags 0x%b\n", + sc->sc_dvname, target, lun, + ti->ti_maxsynch.period, + ti->ti_maxsynch.offset, + ti->ti_flags, SCSI_LOW_BITS); + return 0; + } + + /********************************************************** + * DEBUG SECTION + **********************************************************/ + static u_char *phase[] = + { + "FREE", "ARBSTART", "SELSTART", "SELECTED", + "CMDOUT", "DATA", "MSGIN", "MSGOUT", "STATIN", "DISC", + "COMPSEQ", "RESEL", "EXPMSGOUT" + }; + + void + scsi_low_print(sc, ti) + struct scsi_low_softc *sc; + struct targ_info *ti; + { + struct ccb *cb = sc->sc_nexus; + + if (ti == NULL) + ti = cb ? cb->ti : NULL; + + printf("%s targ 0x%x nexus 0x%x discs %d\n", + sc->sc_dvname, ti, cb, sc->sc_disc); + + /* target stat */ + if (ti) + { + struct sc_p *sp = &sc->sc_scp; + u_int lun = cb ? cb->lun : 0; + + printf("%s(%d:%d) ph<%s> ", sc->sc_dvname, + ti->ti_id, lun, phase[(int) ti->ti_phase]); + + printf("msgptr %x msg[0] %x status %x tflags %x\n", + (u_int) (ti->ti_msginptr), (u_int) (ti->ti_msgin[0]), + ti->ti_status, ti->ti_tflags); + + printf("msgout %x emsgout %x ti_omsglen %x flags %b\n", + (u_int) ti->ti_msgout, (u_int) ti->ti_emsgout, + ti->ti_omsgoutlen, ti->ti_flags, SCSI_LOW_BITS); + + printf("datalen %x dataaddr %x ", sp->datalen, sp->data); + + if (cb) + printf("cmdlen %x cmdaddr %x cmd[0] %x odatalen %x", + cb->cmdlen, cb->cmd, (u_int) cb->cmd[0], + cb->datalen); + + printf("\n"); + printf("error flags %b\n", ti->ti_error, SCSI_LOW_ERRORBITS); + } + } Index: PAO/sys/i386/scsi/scsi_low/scsi_low.h diff -c /dev/null PAO/sys/i386/scsi/scsi_low/scsi_low.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:29 1998 --- PAO/sys/i386/scsi/scsi_low/scsi_low.h Sun Dec 6 07:48:36 1998 *************** *** 0 **** --- 1,387 ---- + /* $NetBSD$ */ + /* $Id: scsi_low.h,v 1.1.8.1 1998/12/05 22:48:36 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1995, 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _SCSI_LOW_H_ + #define _SCSI_LOW_H_ + + #ifdef __NetBSD__ + #include + #endif + #ifdef __FreeBSD__ + #include + #endif + + #define SCSI_LOW_SYNC DVF_SCSI_SYNC + #define SCSI_LOW_DISC DVF_SCSI_DISC + #define SCSI_LOW_WAIT DVF_SCSI_WAIT + #define SCSI_LOW_LINK DVF_SCSI_LINK + #define SCSI_LOW_QTAG DVF_SCSI_QTAG + #define SCSI_LOW_NOPARITY DVF_SCSI_NOPARITY + #define SCSI_LOW_SAVESP DVF_SCSI_SAVESP + #define SCSI_LOW_DEFCFG DVF_SCSI_DEFCFG + #define SCSI_LOW_BITS DVF_SCSI_BITS + + #define SCSI_LOW_PERIOD(XXX) DVF_SCSI_PERIOD(XXX) + #define SCSI_LOW_OFFSET(XXX) DVF_SCSI_OFFSET(XXX) + + #define HOST_SCSI_ID 7 + + #define SCSI_LOW_MIN_TOUT 24 + #define SCSI_LOW_TIMEOUT_CHECK_INTERVAL 4 + #define SCSI_LOW_POWDOWN_TC 15 + + #define NTARGETS 8 + #define MAXMSGLEN 16 + #define MAXRETRY 3 + + struct targ_info; + + struct ccb { + TAILQ_ENTRY(ccb) ccb_chain; + + struct scsi_xfer *xs; /* scsi upper */ + + struct targ_info *ti; /* targ_info */ + + u_int lun; /* lun */ + + int rcnt; /* retry counter */ + + /***************************************** + * scsi cmd & data + *****************************************/ + u_int8_t *cmd; /* scsi cmd */ + int cmdlen; + + u_int8_t *data; /* scsi data */ + u_int datalen; + + u_int8_t msgout[MAXMSGLEN]; /* scsi msgout */ + u_int msgoutlen; + + /***************************************** + * timeout counter + *****************************************/ + int tc; + int tcmax; + }; + + /* ccb assert */ + #ifdef __NetBSD__ + #include + #endif + #ifdef __FreeBSD__ + #include + #endif + + GENERIC_CCB_ASSERT(scsi_low, ccb) + + /* scsi pointer */ + struct sc_p { + u_int8_t *data; + int datalen; + }; + + #define SCSI_LOW_SETUP_PHASE(PHASE) \ + { \ + ti->ti_ophase = ti->ti_phase; \ + ti->ti_phase = (PHASE); \ + } + + #define SCSI_LOW_SETUP_MSGPHASE(PHASE) \ + { \ + sc->sc_msgphase = (PHASE); \ + } + + struct scsi_low_softc; + + struct targ_info { + TAILQ_ENTRY(targ_info) ti_chain; /* targ_info link */ + + struct scsi_low_softc *ti_sc; /* our softc */ + u_int ti_id; /* scsi id */ + + #define TARG_CA 0x01 + #define TARG_SYNCH_PEND 0x02 + u_int ti_tflags; /* target state I */ + + #define UNIT_RDY 0x00 + #define UNIT_START 0x01 + #define UNIT_SYNCH 0x02 + #define UNIT_OK 0x03 + u_int ti_state; /* target state II */ + + u_int ti_flags; + u_int ti_cfgflags; + u_int ti_quirks; + + #define FATALIO 0x01 + #define ABORTIO 0x02 + #define TIMEOUTIO 0x04 + #define PDMAERR 0x08 + #define MSGERR 0x10 + #define PARITYERR 0x20 + #define ERRBUSY 0x40 + #define SCSI_LOW_ERRORBITS "\020\007busy\006parity\005msgerr\004pdmaerr\003timeout\002abort\001fatal" + u_int ti_error; /* error flags */ + + /***************************************** + * scsi phase data + *****************************************/ + struct sc_p ti_sscp; /* saved scsi data pointer */ + + #define PH_NULL 0x00 + #define PH_ARBSTART 0x01 + #define PH_SELSTART 0x02 + #define PH_SELECTED 0x03 + #define PH_CMD 0x04 + #define PH_DATA 0x05 + #define PH_MSGIN 0x06 + #define PH_MSGOUT 0x07 + #define PH_STAT 0x08 + #define PH_DISC 0x09 + #define PH_COMPSEQ 0x0a + #define PH_RESEL 0x0b + #define PH_MSGOUTEXP 0x0c + u_int ti_phase; /* scsi phase */ + u_int ti_ophase; /* old scsi phase */ + + u_int8_t ti_status; /* status in */ + + u_int ti_msginptr; /* msgin ptr */ + u_int8_t ti_msgin[MAXMSGLEN]; /* msgin buffer */ + + u_int8_t ti_msgout; /* last msgout byte */ + u_int8_t ti_emsgout; /* last msgout byte */ + u_int ti_omsgoutlen; /* for retry msgout */ + + struct synch { + u_int8_t offset; + u_int8_t period; + u_int8_t c3img; + } ti_synch, ti_maxsynch; /* synch data */ + + struct ccb *ti_disccb; /* disconnected */ + }; + + /************************************************* + * COMMON HEADER STRUCTURE + *************************************************/ + struct scsi_low_softc; + typedef struct scsi_low_softc *sc_low_t; + + #define SC_LOW_RESET_T (int (*) __P((sc_low_t, int))) + #define SC_LOW_BUSRST_T (void (*) __P((sc_low_t))) + #define SC_LOW_SELECT_T (int (*) __P((sc_low_t, struct ccb *))) + #define SC_LOW_ATTEN_T (void (*) __P((sc_low_t))) + #define SC_LOW_SYNCH_T (int (*) __P((sc_low_t, struct targ_info *, u_int, u_int))) + #define SC_LOW_INTR_T (int (*) __P((void *))) + #define SC_LOW_POWER_T (int (*) __P((sc_low_t, u_int))) + + struct scsi_low_funcs { + int (*scsi_low_reset) __P((sc_low_t, int)); + void (*scsi_low_bus_reset) __P((sc_low_t)); + + int (*scsi_low_start_bus) __P((sc_low_t, struct ccb *)); + + void (*scsi_low_attention) __P((sc_low_t)); + int (*scsi_low_synch) __P((sc_low_t, struct targ_info *, u_int, u_int)); + int (*scsi_low_intr) __P((void *)); + + #define SCSI_LOW_POWDOWN 1 + #define SCSI_LOW_ENGAGE 2 + int (*scsi_low_power) __P((sc_low_t, u_int)); + }; + + /* sc_flags */ + #define HW_POWDOWN 0x01 + #define HW_RESUME 0x02 + #define HW_PDMASTART 0x04 + #define HW_INACTIVE 0x08 + + /* msg phase */ + #define NOMSG 0x00 + #define DISCASSERT 0x01 + #define CMDCOMPLETE 0x02 + + /* read write */ + #define SCSI_LOW_WRITE 0 + #define SCSI_LOW_READ 1 + + #define CFG_NODISC 0x01 + #define CFG_NOPARITY 0x02 + #define CFG_NOATTEN 0x04 + #define CFG_ASYNC 0x08 + + TAILQ_HEAD(targ_info_tab, targ_info); + + #define SCSI_LOW_DVNAME_LEN 16 + + #define SCSI_LOW_SOFTC \ + OS_DEPEND_DEVICE_HEADER \ + OS_DEPEND_MISC_HEADER \ + OS_DEPEND_SCSI_HEADER \ + \ + struct targ_info *sc_ti[NTARGETS]; \ + \ + struct targ_info_tab sc_titab; \ + \ + struct ccbtab sc_start; \ + struct ccb *sc_nexus; \ + \ + int sc_disc; \ + struct targ_info *sc_selid; \ + \ + u_int sc_flags; \ + \ + u_int sc_msgphase; \ + \ + struct sc_p sc_scp; \ + \ + u_int sc_direction; \ + int sc_tdatalen; \ + \ + u_int sc_mask; \ + int sc_wc; \ + \ + u_int sc_oc; \ + int sc_powc; \ + u_int sc_rstep; \ + \ + u_int sc_cfgflags; \ + \ + struct scsi_low_funcs *sc_funcs; \ + \ + struct scsi_sense sc_sense_cmd; \ + struct scsi_sense_data sc_sense; \ + \ + u_char sc_dvname[SCSI_LOW_DVNAME_LEN]; + + /************************************************* + * SCSI LOW SOFTC + *************************************************/ + struct scsi_low_softc { + SCSI_LOW_SOFTC + }; + + /************************************************* + * PROTOTYPE + *************************************************/ + int scsi_low_attach __P((struct scsi_low_softc *)); + void scsi_low_timeout __P((void *)); + int scsi_low_scsi_cmd __P((struct scsi_xfer *)); + void scsi_low_scsi_minphys __P((struct buf *)); + void scsi_low_start __P((struct scsi_low_softc *)); + int scsi_low_done __P((void *, struct ccb *)); + void scsi_low_reset_nexus __P((struct scsi_low_softc *, int)); + int scsi_low_msgout __P((struct scsi_low_softc *, struct targ_info *, struct ccb *)); + void scsi_low_msgin __P((struct scsi_low_softc *, struct ccb *)); + int scsi_low_restart __P((struct scsi_low_softc *, u_char *)); + void scsi_low_free_ti __P((struct scsi_low_softc *)); + struct targ_info *scsi_low_alloc_ti __P((struct scsi_low_softc *, int)); + + #define SCSI_LOW_LUNUNK ((u_int) -1) + struct ccb *scsi_low_reselected __P((struct scsi_low_softc *, u_int, u_int)); + int scsi_low_disconnected __P((struct scsi_low_softc *, struct ccb *)); + + /* reset */ + #define SCSI2_RESET_DELAY 5000000 + #define TWIDDLEWAIT 10000 + void scsi_low_twiddle_wait __P((void)); + void scsi_low_bus_reset __P((struct scsi_low_softc *)); + + void scsi_low_print __P((struct scsi_low_softc *, struct targ_info *)); + + int scsi_low_target_open __P((struct scsi_link *, struct cfdata *)); + void scsi_low_calcf __P((struct targ_info *)); + int scsi_low_reset __P((struct scsi_low_softc *, u_int)); + + #ifdef __NetBSD__ + int scsi_low_activate __P((pisa_device_args_t)); + int scsi_low_deactivate __P((pisa_device_args_t)); + #endif + + #ifdef __FreeBSD__ + int scsi_low_activate __P((struct scsi_low_softc *, struct isa_device *)); + int scsi_low_deactivate __P((struct scsi_low_softc *)); + #endif + + /* misc */ + static inline u_int8_t scsi_low_identify __P((struct targ_info *ti)); + + static inline u_int8_t + scsi_low_identify(ti) + struct targ_info *ti; + { + + return (ti->ti_flags & SCSI_LOW_DISC) ? 0xc0 : 0x80; + } + + #define ID_MSG_SETUP(TI, CB) \ + { \ + (TI)->ti_msgout = scsi_low_identify(TI) | (CB)->lun; \ + (TI)->ti_omsgoutlen = 0; \ + } + + /* XXX: use scsi_message.h */ + #define ST_GOOD 0x00 + #define ST_CHKCOND 0x02 + #define ST_MET 0x04 + #define ST_BUSY 0x08 + #define ST_INTERGOOD 0x10 + #define ST_INTERMET 0x14 + #define ST_CONFLICT 0x18 + #define ST_QUEFULL 0x28 + + #define MSG_COMP 0x00 + #define MSG_EXTEND 0x01 + + #define MKMSG_EXTEND(XLEN, XCODE) ((((u_int)(XLEN)) << NBBY) | ((u_int)(XCODE))) + #define MSG_EXTEND_MDPCODE 0x00 + #define MSG_EXTEND_MDPLEN 0x05 + #define MSG_EXTEND_SYNCHCODE 0x01 + #define MSG_EXTEND_SYNCHLEN 0x03 + #define MSG_EXTEND_WIDECODE 0x03 + #define MSG_EXTEND_WIDELEN 0x02 + + #define MSG_SAVESP 0x02 + #define MSG_RESTORESP 0x03 + #define MSG_DISCON 0x04 + #define MSG_I_ERROR 0x05 + #define MSG_ABORT 0x06 + #define MSG_REJECT 0x07 + #define MSG_NOOP 0x08 + #define MSG_PARITY 0x09 + #define MSG_LCOMP 0x0a + #define MSG_LCOMP_F 0x0b + #define MSG_RESET 0x0c + #endif /* !_SCSI_LOW_H_ */ Index: PAO/sys/i386/scsi/scsi_low/scsi_low_if.h diff -c /dev/null PAO/sys/i386/scsi/scsi_low/scsi_low_if.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:29 1998 --- PAO/sys/i386/scsi/scsi_low/scsi_low_if.h Sun Dec 6 07:48:37 1998 *************** *** 0 **** --- 1,127 ---- + /* + * Copyright (c) HONDA Naofumi, KATO Takenori, 1996. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /* $Id: scsi_low_if.h,v 1.1.8.1 1998/12/05 22:48:37 itojun Exp $ */ + + /*************************************************** + * misc device header in scsi_low_softc + ***************************************************/ + #ifdef __NetBSD__ + #define OS_DEPEND_DEVICE_HEADER \ + struct device sc_dev; \ + void *sc_ih; + + #define OS_DEPEND_SCSI_HEADER \ + struct scsi_link sc_link; + + #define OS_DEPEND_MISC_HEADER \ + pisa_device_handle_t sc_pdv; \ + bus_chipset_tag_t sc_bc; \ + bus_io_handle_t sc_ioh; \ + bus_io_handle_t sc_delayioh; \ + bus_mem_handle_t sc_memh; + + #endif /* __NetBSD__ */ + #ifdef __FreeBSD__ + #define OS_DEPEND_DEVICE_HEADER \ + struct device sc_dev; \ + int unit; + + #define OS_DEPEND_SCSI_HEADER \ + struct scsi_link sc_link; + + #define OS_DEPEND_MISC_HEADER \ + int sc_ioport; + #endif /* __FreeBSD__ */ + + + /*************************************************** + * include + ***************************************************/ + /* (I) common include */ + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + /* (II) os depend include */ + #ifdef __NetBSD__ + #include + + #include + #include + #include + + #include + #include + #include + #include + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #endif /* __FreeBSD__ */ + + #include + #include + #include + + /*************************************************** + * BUS IO MAPPINGS & BS specific inclusion + ***************************************************/ + #ifdef __NetBSD__ + #include + #include + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + #define SCSI_POLL SCSI_NOMASK + #define delay(y) DELAY(y) + + #if 0 + #include + #endif + + #include + #include + #endif /* __FreeBSD__ */ Index: PAO/sys/i386/scsi/scsi_low/scsi_low_pisa.c diff -c /dev/null PAO/sys/i386/scsi/scsi_low/scsi_low_pisa.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:29 1998 --- PAO/sys/i386/scsi/scsi_low/scsi_low_pisa.c Sun Dec 6 07:48:38 1998 *************** *** 0 **** --- 1,143 ---- + /* $NetBSD$ */ + /* $Id: scsi_low_pisa.c,v 1.1.8.1 1998/12/05 22:48:38 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1995, 1996 Naofumi HONDA. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifdef __NetBSD__ + #include + #endif /* __NetBSD__ */ + #ifdef __FreeBSD__ + #include + #endif /* __FreeBSD__ */ + + #ifdef __NetBSD__ + #define SCSIBUS_RESCAN + #endif + + #ifdef __FreeBSD__ + static inline int + scsi_low_deactivate_1(struct scsi_low_softc *sc) + #else + inline int + scsi_low_deactivate_1(sc) + struct scsi_low_softc *sc; + #endif + { + + sc->sc_flags |= HW_INACTIVE; + + #ifdef SCSI_LOW_POWFUNC + untimeout(scsi_low_recover, sc); + #endif /* SCSI_LOW_POWFUNC */ + untimeout(scsi_low_timeout, sc); + + return 0; + } + + #ifdef __NetBSD__ + int + scsi_low_deactivate(arg) + pisa_device_args_t arg; + { + return (scsi_low_deactivate_1(arg->id)); + } + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + int + scsi_low_deactivate(struct scsi_low_softc *sc) + { + + return (scsi_low_deactivate_1(sc)); + } + #endif /* __FreeBSD__ */ + + #ifdef __FreeBSD__ + static inline int + scsi_low_activate_1(struct scsi_low_softc *sc, int flags) + #else + inline int + scsi_low_activate_1(sc, flags) + struct scsi_low_softc *sc; + int flags; + #endif + { + int i, error; + + sc->sc_flags &= ~HW_INACTIVE; + #ifdef __FreeBSD__ + sc->sc_cfgflags = ((sc->sc_cfgflags << 16) | (flags & 0xffff)); + #else /* __NetBSD__ */ + sc->sc_cfgflags = DVCFG_MKCFG(DVCFG_MAJOR(sc->sc_cfgflags), + DVCFG_MINOR(flags)); + #endif + + #ifdef __NetBSD__ + sc->sc_mask = (1 << ia->ia_irq); + #endif + + if (error = scsi_low_reset(sc, 0)) + { + sc->sc_flags |= HW_INACTIVE; + return error; + } + + timeout(scsi_low_timeout, sc, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz); + + /* rescan the scsi bus */ + #ifdef SCSIBUS_RESCAN + if (arg->event == PISA_EVENT_INSERT && sc->sc_start.tqh_first == NULL) + scsi_probe_busses((int) sc->sc_link.scsibus, -1, -1); + #endif + /* start again */ + scsi_low_start(sc); + return 0; + } + + #ifdef __NetBSD__ + int + scsi_low_activate(arg) + pisa_device_args_t arg; + { + struct isa_attach_args *ia = arg->ia; + + return (scsi_low_activate_1(arg->id, ia->ia_cfgflags)); + } + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + int + scsi_low_activate(sc, dev) + struct scsi_low_softc *sc; + struct isa_device *dev; + { + return (scsi_low_activate_1(sc, dev->id_flags)); + } + #endif /* __FreeBSD__ */ Index: PAO/sys/i386/scsi/tmc18c30/tmc18c30.c diff -c /dev/null PAO/sys/i386/scsi/tmc18c30/tmc18c30.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:30 1998 --- PAO/sys/i386/scsi/tmc18c30/tmc18c30.c Sun Dec 6 07:48:40 1998 *************** *** 0 **** --- 1,829 ---- + /* $NetBSD$ */ + /* $Id: tmc18c30.c,v 1.1.8.1 1998/12/05 22:48:40 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1996 Naofumi HONDA. + * Copyright (c) 1996 Kouichi Matsuda. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifdef __NetBSD__ + #include + #endif + #ifdef __FreeBSD__ + #include + #endif + + /*************************************************** + * USER SETTINGS + ***************************************************/ + /* DEVICE CONFIGURATION FLAGS (MINOR) + * + * 0x01 DISCONECT OFF + * 0x02 PARITY LINE OFF + * 0x04 IDENTIFY MSG OFF ( = single lun) + * 0x08 SYNC TRANSFER OFF + */ + + /* #define STG_SYNC_SUPPORT */ /* NOT YET but easy */ + + /* For the 512 fifo type: change below */ + #define TMC18C30_FIFOSZ 0x800 + #define TMC18C30_FCB 1 + + #define TMC18C50_FIFOSZ 0x2000 + #define TMC18C50_FCB 2 + + /*************************************************** + * DEBUG + ***************************************************/ + #ifndef DDB + #define Debugger() panic("should call debugger here (tmc18c30.c)") + #endif /* ! DDB */ + + #define STG_DEBUG + #ifdef STG_DEBUG + int stg_debug; + + struct stg_statics { + int disconnect; + int reselect; + } stg_statics[NTARGETS]; + #endif /* STG_DEBUG */ + + /************************************************************** + * DECLARE + **************************************************************/ + /* static */ + static void stg_pio_read __P((struct stg_softc *, struct targ_info *)); + static void stg_pio_write __P((struct stg_softc *, struct targ_info *)); + static int stg_xfer __P((struct stg_softc *, u_int8_t *, int, int)); + static int stg_synch __P((struct stg_softc *, struct targ_info *, u_int, u_int)); + static int stg_reselected __P((struct stg_softc *)); + static inline int stg_disconnected __P((struct stg_softc *, struct ccb *cb)); + static inline void stg_pdma_end __P((struct stg_softc *, struct ccb *, struct targ_info *)); + static int stghw_select_targ_wait __P((struct stg_softc *, int)); + static void stghw_init __P((struct stg_softc *)); + static void stghw_synch __P((struct stg_softc *, struct targ_info *)); + + static int stg_world_start __P((struct stg_softc *, int)); + static void stghw_reset __P((struct stg_softc *)); + static int stghw_start_selection __P((struct stg_softc *sc, struct ccb *)); + static void stghw_bus_reset __P((struct stg_softc *)); + static void stghw_attention __P((struct stg_softc *)); + + struct scsi_low_funcs stgfuncs = + { + SC_LOW_RESET_T stg_world_start, + SC_LOW_BUSRST_T stghw_bus_reset, + + SC_LOW_SELECT_T stghw_start_selection, + + SC_LOW_ATTEN_T stghw_attention, + SC_LOW_SYNCH_T stg_synch, + + SC_LOW_INTR_T stg_sequencer, + + NULL, + }; + + /**************************************************** + * hwfuncs + ****************************************************/ + int + stghw_check(sc) + struct stg_softc *sc; + { + u_int16_t lsb, msb; + DECLARE_IOPORT(sc); + + sc->sc_chip = TMCCHIP_UNK; + sc->sc_fsz = TMC18C50_FIFOSZ; + sc->sc_fcb = TMC18C50_FCB; + sc->sc_fcsp = 0; + + sc->sc_fcRinit = FCTL_INTEN; + sc->sc_fcWinit = FCTL_PARENB | FCTL_INTEN; + + if (sc->sc_cfgflags & CFG_NOATTEN) + sc->sc_busc = 0; + else + sc->sc_busc = BCTL_ATN; + + lsb = INB(tmc_idlsb); + msb = INB(tmc_idmsb); + switch (msb << 8 | lsb) + { + case 0x6127: + /* TMCCHIP_1800 not supported. (it's my policy) */ + sc->sc_chip = TMCCHIP_1800; + return EINVAL; + + case 0x60e9: + sc->sc_chip = TMCCHIP_18C50; + sc->sc_fcsp |= FCTL_CLRINT; + if (INB(tmc_cfg2) & 0x02) + { + sc->sc_chip = TMCCHIP_18C30; + sc->sc_fsz = TMC18C30_FIFOSZ; + sc->sc_fcb = TMC18C30_FCB; + } + break; + + default: + return ENODEV; + } + + sc->sc_icinit = ICTL_ALLINT | sc->sc_fcb; + return 0; + } + + static void + stghw_reset(sc) + struct stg_softc *sc; + { + DECLARE_IOPORT(sc); + + OUTB(tmc_ictl, 0); + OUTB(tmc_bctl, BCTL_BUSFREE); + OUTB(tmc_fctl, sc->sc_fcsp | sc->sc_fcRinit | FCTL_CLRFIFO); + OUTB(tmc_fctl, sc->sc_fcRinit); + OUTB(tmc_ictl, sc->sc_icinit); + + OUTB(tmc_ssctl, 0); + } + + static void + stghw_init(sc) + struct stg_softc *sc; + { + DECLARE_IOPORT(sc); + + OUTB(tmc_ictl, 0); + OUTB(tmc_bctl, BCTL_BUSFREE); + OUTB(tmc_fctl, sc->sc_fcsp | sc->sc_fcRinit | FCTL_CLRFIFO); + OUTB(tmc_fctl, sc->sc_fcRinit); + OUTB(tmc_ictl, sc->sc_icinit); + + OUTB(tmc_ssctl, 0); + } + + static void + stghw_synch(sc, ti) + struct stg_softc *sc; + struct targ_info *ti; + { + #ifdef STG_SYNCH + DECLARE_IOPORT(sc); + + OUTB(tmc_ssctl, ti->ti_synch.c3img); + #endif + } + + /**************************************************** + * scsi low interface + ****************************************************/ + static void + stghw_attention(sc) + struct stg_softc *sc; + { + DECLARE_IOPORT(sc); + + OUTB(tmc_bctl, BCTL_BUSEN | BCTL_ATN); + } + + static void + stghw_bus_reset(sc) + struct stg_softc *sc; + { + DECLARE_IOPORT(sc); + + OUTB(tmc_ictl, 0); + OUTB(tmc_fctl, 0); + OUTB(tmc_bctl, BCTL_RST); + delay(100000); + OUTB(tmc_bctl, BCTL_BUSFREE); + } + + static int + stghw_start_selection(sc, cb) + struct stg_softc *sc; + struct ccb *cb; + { + struct targ_info *ti = cb->ti; + register u_int8_t stat; + int s, tc = sc->sc_wc; + DECLARE_IOPORT(sc); + + if (ti->ti_flags & SCSI_LOW_NOPARITY) + sc->sc_fcRinit &= ~FCTL_PARENB; + else + sc->sc_fcRinit |= FCTL_PARENB; + + s = splhigh(); + if (sc->sc_disc > 0) + { + stat = INB(tmc_bstat); + if ((stat & RESEL_PHASE_MASK)== PHASE_RESELECTED) + { + splx(s); + return 1; + } + + if (stat & (BSTAT_BSY | BSTAT_SEL)) + { + delay(1); /* XXX */ + + stat = INB(tmc_bstat); + if (stat & (BSTAT_BSY | BSTAT_SEL)) + { + splx(s); + return 1; + } + } + + OUTB(tmc_bctl, BCTL_BUSFREE); + OUTB(tmc_scsiid, (1 << HOST_SCSI_ID)); + OUTB(tmc_fctl, sc->sc_fcRinit | FCTL_ARBIT); + splx(s); + } + else + { + splx(s); + + do + { + stat = INB(tmc_bstat); + if ((stat & BSTAT_BSY) == 0) + break; + + if (stat & (BSTAT_SEL | BSTAT_REQ)) + { + printf("%s hardware failure(0x%x)\n", + sc->sc_dev.dv_xname, (u_int) stat); + return 1; + } + else if (tc -- <= 0) + { + printf("%s bus free timeout\n", + sc->sc_dev.dv_xname); + return 1; + } + } + while (1); + + OUTB(tmc_bctl, BCTL_BUSFREE); + OUTB(tmc_scsiid, (1 << HOST_SCSI_ID)); + OUTB(tmc_fctl, sc->sc_fcRinit | FCTL_ARBIT); + } + + SCSI_LOW_SETUP_PHASE(PH_ARBSTART); + return 0; + } + + static int + stg_world_start(sc, fdone) + struct stg_softc *sc; + int fdone; + { + struct targ_info *ti; + u_int stat; + int error; + + if (sc->sc_flags & HW_INACTIVE) + return EBUSY; + + /* reset current nexus */ + scsi_low_reset_nexus((struct scsi_low_softc *) sc, fdone); + + sc->sc_cfgflags |= CFG_ASYNC; /* XXX */ + + /* hardware info init */ + for (ti = sc->sc_titab.tqh_first; ti; ti = ti->ti_chain.tqe_next) + { + ti->ti_state = UNIT_RDY; + ti->ti_synch.period = ti->ti_synch.offset = 0; + ti->ti_maxsynch.offset = 8; + + scsi_low_calcf(ti); + } + + if (error = stghw_check(sc)) + return error; + + stghw_reset(sc); + scsi_low_bus_reset((struct scsi_low_softc *) sc); + stghw_init(sc); + + #ifdef __NetBSD__ + softintr(sc->sc_mask); + #endif + return 0; + } + + static int + stg_synch(sc, ti, period, offset) + struct stg_softc *sc; + struct targ_info *ti; + u_int period, offset; + { + u_int res; + + period = period << 2; + + if (period >= 200) + { + ti->ti_synch.c3img = (period - 200) / 50; + if (period % 50) + ti->ti_synch.c3img ++; + ti->ti_synch.c3img |= SSCTL_SYNCHEN; + } + else if (period >= 100) + { + ti->ti_synch.c3img = (period - 100) / 50; + if (period % 50) + ti->ti_synch.c3img ++; + ti->ti_synch.c3img |= SSCTL_SYNCHEN | SSCTL_FSYNCHEN; + } + + ti->ti_synch.period = period; + ti->ti_synch.offset = offset; + return 0; + } + + /************************************************************** + * PDMA functions + **************************************************************/ + static inline void + stg_pdma_end(sc, cb, ti) + struct stg_softc *sc; + struct ccb *cb; + struct targ_info *ti; + { + u_int len, tres; + DECLARE_IOPORT(sc); + + sc->sc_flags &= ~HW_PDMASTART; + + if (ti->ti_phase == PH_DATA) + { + if ((sc->sc_direction & SCSI_LOW_READ) == 0) + { + len = INW(tmc_fdcnt); + if (len) + { + tres = len + sc->sc_scp.datalen; + if (tres <= (u_int) cb->datalen) + { + sc->sc_scp.data -= len; + sc->sc_scp.datalen = tres; + } + else + { + ti->ti_error |= PDMAERR; + printf("%s len %x >= datalen %x\n", + sc->sc_dev.dv_xname, + len, sc->sc_scp.datalen); + } + } + } + } + else + { + + printf("%s data phase miss\n", sc->sc_dev.dv_xname); + ti->ti_error |= PDMAERR; + } + + #ifdef STG_SYNCH + OUTB(tmc_ssctl, 0); + #endif + OUTB(tmc_fctl, sc->sc_fcRinit); + } + + static void + stg_pio_read(sc, ti) + struct stg_softc *sc; + struct targ_info *ti; + { + int tout = sc->sc_wc; + u_int res; + u_int8_t stat; + DECLARE_IOPORT(sc); + + OUTB(tmc_fctl, sc->sc_fcRinit | FCTL_FIFOEN); + + #ifdef STG_SYNCH + stghw_synch(sc, ti); + #endif + + sc->sc_flags |= HW_PDMASTART; + while (sc->sc_scp.datalen > 0 && tout -- > 0) + { + res = INW(tmc_fdcnt); + if (res == 0) + { + stat = INB(tmc_bstat); + if ((stat & BSTAT_PHMASK) == BSTAT_IO) + continue; + break; /* phase mismatch */ + } + + /* XXX */ + if (res > sc->sc_scp.datalen) + break; + + sc->sc_scp.datalen -= res; + if (res & 1) + { + sc->sc_scp.data[0] = INB(tmc_rfifo); + sc->sc_scp.data ++; + res --; + } + + INSW(tmc_rfifo, sc->sc_scp.data, res >> 1); + sc->sc_scp.data += res; + } + + if (tout <= 0) + printf("%s pio read timeout\n", sc->sc_dev.dv_xname); + } + + #define WFIFO_CRIT 0x100 + + static void + stg_pio_write(sc, ti) + struct stg_softc *sc; + struct targ_info *ti; + { + u_int res; + int tout = sc->sc_wc; + register u_int8_t stat; + DECLARE_IOPORT(sc); + + stat = sc->sc_fcWinit | FCTL_FIFOEN | FCTL_FIFOW; + OUTB(tmc_fctl, stat | FCTL_CLRFIFO); + OUTB(tmc_fctl, stat); + + #ifdef STG_SYNCH + stghw_synch(sc, ti); + #endif + + sc->sc_flags |= HW_PDMASTART; + while (sc->sc_scp.datalen > 0 && tout -- > 0) + { + stat = INB(tmc_bstat); + if ((stat & BSTAT_PHMASK) != 0) + break; + + if (INW(tmc_fdcnt) >= WFIFO_CRIT) + continue; + + res = (sc->sc_scp.datalen > WFIFO_CRIT) ? WFIFO_CRIT : + sc->sc_scp.datalen; + sc->sc_scp.datalen -= res; + if ((res & 0x01) != 0) + { + OUTB(tmc_wfifo, *sc->sc_scp.data++); + res --; + } + + OUTSW(tmc_wfifo, sc->sc_scp.data, res >> 1); + sc->sc_scp.data += res; + } + + if (tout <= 0) + printf("%s pio write timeout\n", sc->sc_dev.dv_xname); + } + + static int + stg_xfer(sc, buf, len, phase) + struct stg_softc *sc; + u_int8_t *buf; + int len; + int phase; + { + int wc, ptr; + u_int8_t stat; + DECLARE_IOPORT(sc); + + if (phase & BSTAT_IO) + OUTB(tmc_fctl, sc->sc_fcRinit); + else + OUTB(tmc_fctl, sc->sc_fcWinit); + + for (ptr = 0; len > 0; len --) + { + wc = sc->sc_wc; + + do + { + stat = INB(tmc_bstat); + if ((stat & BSTAT_PHMASK) != (phase & BSTAT_PHMASK)) + goto bad; + if (stat & BSTAT_REQ) + break; + if (wc -- <= 0) + { + printf("%s xfer tout\n", sc->sc_dev.dv_xname); + goto bad; + } + } + while (1); + + if (phase & BSTAT_IO) + buf[ptr ++] = INB(tmc_rdata); + else + OUTB(tmc_wdata, buf[ptr ++]); + } + + bad: + OUTB(tmc_fctl, sc->sc_fcRinit); + return len; + } + + /************************************************************** + * disconnect & reselect (HW low) + **************************************************************/ + static int + stg_reselected(sc) + struct stg_softc *sc; + { + struct ccb *cb; + u_int sid; + DECLARE_IOPORT(sc); + + sid = (u_int) INB(tmc_scsiid); + sid &= ~(1 << HOST_SCSI_ID); + sid = ffs(sid) - 1; + cb = scsi_low_reselected((struct scsi_low_softc *) sc, sid, SCSI_LOW_LUNUNK); + if (cb == NULL) + return 0; + + #ifdef STG_DEBUG + stg_statics[sid].reselect ++; + #endif + + /* assert a busy line and ack the selection */ + OUTB(tmc_scsiid, (1 << HOST_SCSI_ID) || (1 << sid)); + OUTB(tmc_fctl, sc->sc_fcsp | + sc->sc_fcRinit | FCTL_CLRFIFO); + OUTB(tmc_fctl, sc->sc_fcRinit); + OUTB(tmc_bctl, BCTL_BSY | BCTL_BUSEN); + return 1; + } + + static inline int + stg_disconnected(sc, cb) + struct stg_softc *sc; + struct ccb *cb; + { + DECLARE_IOPORT(sc); + + /* clear bus status & fifo */ + OUTB(tmc_fctl, sc->sc_fcRinit | FCTL_CLRFIFO); + OUTB(tmc_fctl, sc->sc_fcRinit); + OUTB(tmc_bctl, BCTL_BUSFREE); + + #ifdef STG_DEBUG + if (sc->sc_msgphase == DISCASSERT) + stg_statics[cb->ti->ti_id].disconnect ++; + #endif + scsi_low_disconnected((struct scsi_low_softc *) sc, cb); + scsi_low_start((struct scsi_low_softc *) sc); + return 1; + } + + /************************************************************** + * SEQUENCER + **************************************************************/ + static int + stghw_select_targ_wait(sc, targ) + struct stg_softc *sc; + int targ; + { + int wc, error = EIO; + DECLARE_IOPORT(sc); + + OUTB(tmc_scsiid, (1 << HOST_SCSI_ID) | (1 << targ)); + OUTB(tmc_fctl, sc->sc_fcWinit & (~FCTL_INTEN)); + OUTB(tmc_bctl, BCTL_BUSEN | BCTL_SEL | sc->sc_busc); + + for (wc = 50000; wc; wc--) + { + if (INB(tmc_bstat) & BSTAT_BSY) + { + error = 0; + break; + } + + delay(1); + } + + OUTB(tmc_fctl, sc->sc_fcRinit | FCTL_CLRFIFO); + OUTB(tmc_fctl, sc->sc_fcRinit); + return error; + } + + int + stg_sequencer(sc) + struct stg_softc *sc; + { + struct targ_info *ti; + struct ccb *cb; + int len; + u_int8_t status, astatus; + DECLARE_IOPORT(sc); + + /******************************************* + * interrupt check + *******************************************/ + if (sc->sc_flags & HW_INACTIVE) + return 0; + + astatus = INB(tmc_astat); + status = INB(tmc_bstat); + + if ((astatus & ASTAT_STATMASK) == 0) + return 0; + + if (astatus & ASTAT_SCSIRST) + { + OUTB(tmc_fctl, + sc->sc_fcRinit | FCTL_CLRFIFO); + OUTB(tmc_fctl, sc->sc_fcRinit); + return 1; + } + + /******************************************* + * debug section + *******************************************/ + #ifdef STG_DEBUG + if (stg_debug) + { + scsi_low_print((struct scsi_low_softc *) sc, NULL); + printf("%s st %x ist %x\n\n", sc->sc_dev.dv_xname, + status, astatus); + if (stg_debug > 1) + Debugger(); + } + #endif /* STG_DEBUG */ + + /******************************************* + * reselection & nexus + *******************************************/ + if ((status & RESEL_PHASE_MASK)== PHASE_RESELECTED) + return stg_reselected(sc); + + if ((cb = sc->sc_nexus) == NULL) + return 0; + ti = cb->ti; + + if ((astatus & ASTAT_PARERR) && + ti->ti_phase != PH_ARBSTART && + (ti->ti_flags & SCSI_LOW_NOPARITY) == 0) + { + ti->ti_error |= PARITYERR; + scsi_low_restart((struct scsi_low_softc *) sc, + "scsi bus parity error"); + return 1; + } + + /******************************************* + * aribitration & selection + *******************************************/ + switch (ti->ti_phase) + { + case PH_ARBSTART: + OUTB(tmc_fctl, + sc->sc_fcRinit | FCTL_CLRFIFO); + + if ((astatus & ASTAT_ARBIT) == 0) + { + OUTB(tmc_fctl, sc->sc_fcRinit); + SCSI_LOW_SETUP_PHASE(PH_NULL); + sc->sc_selid = NULL; + sc->sc_nexus = NULL; + return 1; + } + else + OUTB(tmc_fctl, sc->sc_fcWinit); + + /* assert select line */ + OUTB(tmc_scsiid, + (1 << HOST_SCSI_ID) | (1 << ti->ti_id)); + OUTB(tmc_bctl, + BCTL_SEL | BCTL_BUSEN | sc->sc_busc); + SCSI_LOW_SETUP_PHASE(PH_SELSTART); + return 1; + + case PH_SELSTART: + sc->sc_selid = NULL; + if ((status & BSTAT_BSY) == 0) + if (stghw_select_targ_wait(sc, ti->ti_id)) + return stg_disconnected(sc, cb); + + /* attention assert */ + OUTB(tmc_fctl, sc->sc_fcRinit); + OUTB(tmc_bctl, BCTL_BUSEN | sc->sc_busc); + SCSI_LOW_SETUP_PHASE(PH_SELECTED); + return 1; + + case PH_RESEL: + /* clear a busy line */ + OUTB(tmc_fctl, sc->sc_fcRinit); + OUTB(tmc_bctl, BCTL_BUSEN); + break; + } + + /******************************************* + * scsi seq + *******************************************/ + if (sc->sc_flags & HW_PDMASTART) + stg_pdma_end(sc, cb, ti); + + switch (status & PHASE_MASK) + { + case COMMAND_PHASE: + SCSI_LOW_SETUP_PHASE(PH_CMD); + stg_xfer(sc, cb->cmd, cb->cmdlen, COMMAND_PHASE); + break; + + case DATA_OUT_PHASE: + SCSI_LOW_SETUP_PHASE(PH_DATA); + sc->sc_direction = SCSI_LOW_WRITE; + stg_pio_write(sc, ti); + break; + + case DATA_IN_PHASE: + SCSI_LOW_SETUP_PHASE(PH_DATA); + sc->sc_direction = SCSI_LOW_READ; + stg_pio_read(sc, ti); + break; + + case STATUS_PHASE: + SCSI_LOW_SETUP_PHASE(PH_STAT); + ti->ti_status = INB(tmc_rdata); + break; + + case MESSAGE_OUT_PHASE: + OUTB(tmc_fctl, sc->sc_fcWinit); + len = scsi_low_msgout((struct scsi_low_softc *) sc, ti, cb); + if (len == 0) + { + if (cb->msgoutlen == 0) + OUTB(tmc_bctl, BCTL_BUSEN); + OUTB(tmc_wdata, ti->ti_msgout); + } + else if (len > 0) + { + stg_xfer(sc, cb->msgout, len, MESSAGE_OUT_PHASE); + OUTB(tmc_bctl, BCTL_BUSEN); + } + OUTB(tmc_fctl, sc->sc_fcRinit); + break; + + case MESSAGE_IN_PHASE: + SCSI_LOW_SETUP_PHASE(PH_MSGIN); + ti->ti_msgin[ti->ti_msginptr++] = INB(tmc_rdata); + scsi_low_msgin((struct scsi_low_softc *)sc, cb); + if (sc->sc_msgphase) + return stg_disconnected(sc, cb); + break; + + case BUSFREE_PHASE: + printf("%s unexpected disconnection\n", sc->sc_dev.dv_xname); + return stg_disconnected(sc, cb); + + default: + printf("%s unknown phase bus %x intr %x\n", + sc->sc_dev.dv_xname, status, astatus); + break; + } + + return 1; + } Index: PAO/sys/i386/scsi/tmc18c30/tmc18c30if.c diff -c /dev/null PAO/sys/i386/scsi/tmc18c30/tmc18c30if.c:1.1.8.1 *** /dev/null Fri Dec 25 10:51:30 1998 --- PAO/sys/i386/scsi/tmc18c30/tmc18c30if.c Sun Dec 6 07:48:44 1998 *************** *** 0 **** --- 1,433 ---- + /* $NetBSD$ */ + /* $Id: tmc18c30if.c,v 1.1.8.1 1998/12/05 22:48:44 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1996 Naofumi HONDA. + * Copyright (c) 1996 Kouichi Matsuda. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifdef __NetBSD__ + #include + #endif + #ifdef __FreeBSD__ + #include + #include "stg.h" + #endif + + /*************************************************** + * PARAMS + ***************************************************/ + #define STG_MAX_CCB (2 * (NTARGETS - 1)) + + /*************************************************** + * ISA DEVICE STRUCTURE + ***************************************************/ + #ifdef __NetBSD__ + int stgintr __P((void *)); + + struct cfdriver stg_cd = { + NULL, "stg", DV_DULL + }; + + struct scsi_device stg_dev = { + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + }; + + struct scsi_adapter stg = { + scsi_low_scsi_cmd, + scsi_low_scsi_minphys, + scsi_low_target_open, + 0, + }; + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + /*void stgintr (int unit);*/ + + /* pccard support */ + #if NCARD > 0 + static int stg_card_intr(struct pccard_devinfo *); + static void stg_card_unload(struct pccard_devinfo *); + static int stg_card_resume(struct stg_softc *); + static int stg_card_init(struct pccard_devinfo *); + + static struct pccard_device stg_info = { + "stg", + stg_card_init, + stg_card_unload, + stg_card_intr, + 0, /* Attributes - presently unused */ + &bio_imask /* Interrupt mask for device */ + /* This should also include net_imask?? */ + }; + + DATA_SET(pccarddrv_set, stg_info); + + #ifdef SCSI_DETACH + static void stgdetach(struct isa_device *dev); + #endif + #endif /* NCARD */ + + struct isa_driver stgdriver = { + stgprobe, + stgattach, + "stg" + }; + + struct scsi_device stg_dev = { + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + "stg", + 0, + {0, 0} + }; + + static struct scsi_adapter stg = { + scsi_low_scsi_cmd, + scsi_low_scsi_minphys, + scsi_low_target_open, + 0, + stg_adapter_info, + "stg", + {0, 0}, + }; + u_int32_t stg_adapter_info (int unit) + { + return 1; + } + + static struct stg_softc *stgdata[NSTG]; + #endif /* __FreeBSD__ */ + + /************************************************************** + * DECLARE + **************************************************************/ + extern int delaycount; + extern struct scsi_low_funcs stgfuncs; + + /************************************************************** + * General probe attach + **************************************************************/ + #ifdef __FreeBSD__ + #if NCARD > 0 + static int + stg_card_resume(struct stg_softc *sc) + { + #if 0 /* XXX stg_init */ + if (!stg_init(sc)) + return (ENXIO); + #endif + printf("%s: resumed\n", sc->sc_dvname); + return (0); + } + + static int + stg_card_init(struct pccard_devinfo *devi) + { + int unit = devi->pd_unit; + struct stg_softc *sc = stgdata[unit]; + + if (NSTG <= unit) + return (ENODEV); + /* XXX -- ncv_init */ + printf("probe stg\n"); + if (stgprobe(&devi->isahd) == 0) + return (ENXIO); + printf("attach stg\n"); + if (stgattach(&devi->isahd) == 0) + return (ENXIO); + return (0); + } + + static void + stg_card_unload(struct pccard_devinfo *devi) + { + struct stg_softc *sc = stgdata[devi->pd_unit]; + + printf("%s: unload\n", sc->sc_dvname); + /* scsi_low_deactivate((struct scsi_low_softc *)sc); */ + #ifdef SCSI_DETACH + stgdetach(&devi->isahd); + #endif + } + + static int + stg_card_intr(struct pccard_devinfo *devi) + { + + (void) stg_sequencer(stgdata[devi->pd_unit]); + return 1; + } + #endif /* NCARD > 0 */ + #endif /* FreeBSD */ + + #ifdef __NetBSD__ + int + stgprobe(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; + { + struct stg_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + struct stg_hw *hw; + int rv = 0; + DECLARE_IOPORT(sc); + + if (ia->ia_iobase == IOBASEUNK || ia->ia_irq == IRQUNK) + return 0; + + bc = ia->ia_bc; + if (bus_io_map(bc, ia->ia_iobase, STGIOSZ, &ioh)) + return 0; + + sc->sc_bc = bc; + sc->sc_ioh = ioh; + sc->sc_dealyioh = ia->ia_delayioh; + #ifdef __FreeBSD__ + sc->sc_cfgflags = (ia->ia_cfgflags & 0xffff); + #else /* __NetBSD__ */ + sc->sc_cfgflags = DVCFG_MINOR(ia->ia_cfgflags); + #endif + sc->sc_wc = delaycount * 2000; /* 2 sec */ + sc->sc_funcs = &stgfuncs; + + if (stghw_check(sc)) + goto bad; + + if (scsi_low_attach((struct scsi_low_softc *) sc)) + goto bad; + + ia->ia_iosize = STGIOSZ; + rv = 1; + + bad: + bus_io_unmap(bc, ioh, STGIOSZ); + return rv; + } + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + static int stghw_probe (struct stg_softc *sc, int flags) + { + sc->sc_cfgflags = flags; + sc->sc_wc = delaycount * 2000; /* 2 sec */ + sc->sc_funcs = &stgfuncs; + return (stghw_check(sc)); + } + + int stgprobe(struct isa_device *dev) + { + struct stg_softc *sc; + int unit = dev->id_unit; + struct stg_hw *hw; + char dvname[SCSI_LOW_DVNAME_LEN]; + DECLARE_IOPORT(sc); + + sprintf(dvname, "stg%d", unit); + + if (unit >= NSTG && !dev->id_reconfig) + { + printf("%s: unit number too high\n", dvname); + return (0); + } + + if (dev->id_iobase == 0) + { + printf("%s: no ioaddr is given\n", dvname); + return (0); + } + + if (dev->id_reconfig || stgdata[unit] != NULL) + { + sc = stgdata[unit]; + sc->sc_ioport = dev->id_iobase; + + #ifdef __FreeBSD__ + if (stghw_probe(sc, dev->id_flags & 0xffff)) + return (0); + #else /* __NetBSD__ */ + if (stghw_probe(sc, DVCFG_MINOR(dev->id_flags))) + return (0); + #endif + } + else + { + sc = malloc(sizeof(struct stg_softc), M_TEMP, M_NOWAIT); + if (sc == NULL) + { + printf("%s: cannot malloc!\n", sc->sc_dvname); + return (0); + } + bzero(sc, sizeof(struct stg_softc)); + strcpy (sc->sc_dvname, dvname); + sc->unit = unit; + stgdata[unit] = sc; + sc->sc_ioport = dev->id_iobase; + + if (stghw_probe(sc, dev->id_flags)) + { + free(sc, M_TEMP); + stgdata[unit] = NULL; + return (0); + } + } + return (STGIOSZ); + } + #endif + + int + stgprint(aux, name) + void *aux; + char *name; + { + + if (name != NULL) + printf("%s: scsibus ", name); + return UNCONF; + } + + #ifdef __FreeBSD__ + #define adapter_target adapter_targ + #define openings opennings + #endif + + #ifdef __FreeBSD__ + static inline void + stg_setup_sc(struct stg_softc *sc) + #else + inline void stg_setup_sc(sc) + struct stg_softc *sc; + #endif + { + + scsi_low_init_ccbque(STG_MAX_CCB); + TAILQ_INIT(&sc->sc_start); + + sc->sc_link.adapter_softc = sc; + sc->sc_link.adapter_target = 7; + sc->sc_link.adapter = &stg; + sc->sc_link.device = &stg_dev; + sc->sc_link.openings = 2; + } + + #undef adapter_target + #undef openings + + #ifdef __NetBSD__ + void + stgattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; + { + struct stg_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + + printf("\n"); + + sc->sc_bc = ia->ia_bc; + sc->sc_dealyioh = ia->ia_delayioh; + if (bus_io_map(sc->sc_bc, ia->ia_iobase, STGIOSZ, &sc->sc_ioh)) + panic("%s: couldn't map io\n", sc->sc_dev.dv_xname); + + stg_setup_sc(sc); + sc->sc_mask = (1 << ia->ia_irq); + sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, + IPL_BIO, stgintr, sc); + + timeout(scsi_low_timeout, sc, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz); + } + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + + #ifdef SCSI_DETACH + static void + stgdetach(struct isa_device *dev) + { + int unit = dev->id_unit; + struct scsibus_data *scbus; + + scbus = (struct scsibus_data *)scsi_extend_get(stgdata[unit]->sc_link.scsibus); + } + #endif + + int + stgattach(dev) + struct isa_device *dev; + { + int unit = dev->id_unit; + struct stg_softc *sc = stgdata[unit]; + struct scsibus_data *scbus; + + if (scsi_low_attach((struct scsi_low_softc *) sc)) + { + printf("%s: scsi low attach failed\n", sc->sc_dvname); + return (0); + } + stg_setup_sc(sc); + sc->sc_link.adapter_unit = unit; + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if (!scbus) + return (0); + scbus->adapter_link = &sc->sc_link; + /* + * ask the adapter what subunits are present + */ + scsi_attachdevs(scbus); + timeout(scsi_low_timeout, sc, SCSI_LOW_TIMEOUT_CHECK_INTERVAL * hz); + return 1; + } + #endif /* __FreeBSD__ */ + + #ifdef __NetBSD__ + int stgintr (arg) + void *arg; + { + return (stg_sequencer((struct stg_softc *)arg)); + } + #endif + + #ifdef __FreeBSD__ + void + stgintr (int unit) + { + (void) stg_sequencer(stgdata[unit]); + } + #endif Index: PAO/sys/i386/scsi/tmc18c30/tmc18c30if.h diff -c /dev/null PAO/sys/i386/scsi/tmc18c30/tmc18c30if.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:31 1998 --- PAO/sys/i386/scsi/tmc18c30/tmc18c30if.h Sun Dec 6 07:48:45 1998 *************** *** 0 **** --- 1,107 ---- + /* + * Copyright (c) HONDA Naofumi, KATO Takenori, 1996. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /* $Id: tmc18c30if.h,v 1.1.8.1 1998/12/05 22:48:45 itojun Exp $ */ + + /*************************************************** + * BUS IO MAPPINGS & TMC18C30 specific inclusion + ***************************************************/ + #ifdef __NetBSD__ + #include + #include + #include + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + #include + #include + #include + + #include "apm.h" + #if NAPM > 0 + #include + #endif /* NAPM > 0 */ + + /* pccard support */ + #include "card.h" + #if NCARD > 0 + #include + #include + #include + #include + #endif /* NCARD > 0 */ + #endif /* __FreeBSD__ */ + + int stg_sequencer __P((struct stg_softc *sc)); + int stghw_check __P((struct stg_softc *)); + + /* (II) os depend declare */ + #ifdef __NetBSD__ + int stgprobe __P((struct device *, struct device *, void *)); + void stgattach __P((struct device *, struct device *, void *)); + #endif /* __NetBSD__ */ + + #ifdef __FreeBSD__ + int stgprobe __P((struct isa_device *dev)); + int stgattach __P((struct isa_device *dev)); + u_int32_t stg_adapter_info __P((int)); + #endif /* __FreeBSD__ */ + + #ifdef __NetBSD__ + #define DECLARE_IOPORT(sc) \ + register bus_chipset_tag_t bc = (sc)->sc_bc; \ + register bus_io_handle_t ioh = (sc)->sc_ioh; + #define OUTB(o, val) \ + bus_io_write_1 (bc, ioh, (o), (val)) + #define OUTW(o, val) \ + bus_io_write_2 (bc, ioh, (o), (val)) + #define OUTSW(o,b,l) \ + bus_io_write_multi_2(bc, ioh, (o), (b), (l)) + #define INB(o) \ + bus_io_read_1 (bc, ioh, (o)) + #define INW(o) \ + bus_io_read_2 (bc, ioh, (o)) + #define INSW(o,b,l) \ + bus_io_read_multi_2(bc, ioh, (o), (b), (l)) + #endif + + #ifdef __FreeBSD__ + #define DECLARE_IOPORT(sc) \ + register int ioport = (sc)->sc_ioport; + #define OUTB(o, val) \ + outb((o)+ioport, (val)) + #define OUTW(o, val) \ + outw((o)+ioport, (val)) + #define OUTSW(o,b,l) \ + outsw((o)+ioport, (b), (l)) + #define INB(o) \ + inb((o)+ioport) + #define INW(o) \ + inw((o)+ioport) + #define INSW(o,b,l) \ + insw((o)+ioport, (b), (l)) + #endif Index: PAO/sys/i386/scsi/tmc18c30/tmc18c30reg.h diff -c /dev/null PAO/sys/i386/scsi/tmc18c30/tmc18c30reg.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:31 1998 --- PAO/sys/i386/scsi/tmc18c30/tmc18c30reg.h Sun Dec 6 07:48:46 1998 *************** *** 0 **** --- 1,141 ---- + /* $NetBSD$ */ + /* $Id: tmc18c30reg.h,v 1.1.8.1 1998/12/05 22:48:46 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1996 Kouichi Matsuda. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _TMC18C30REG_H_ + #define _TMC18C30REG_H_ + + #define tmc_wdata 0x00 + #define tmc_rdata 0x00 + + #define tmc_bctl 0x01 + #define BCTL_BUSFREE 0x00 + #define BCTL_RST 0x01 + #define BCTL_SEL 0x02 + #define BCTL_BSY 0x04 + #define BCTL_ATN 0x08 + #define BCTL_IO 0x10 + #define BCTL_CD 0x20 + #define BCTL_MSG 0x40 + #define BCTL_BUSEN 0x80 + #define tmc_bstat 0x01 + #define BSTAT_BSY 0x01 + #define BSTAT_MSG 0x02 + #define BSTAT_IO 0x04 + #define BSTAT_CMD 0x08 + #define BSTAT_REQ 0x10 + #define BSTAT_SEL 0x20 + #define BSTAT_ACK 0x40 + #define BSTAT_PHMASK (BSTAT_MSG | BSTAT_IO | BSTAT_CMD) + + #define tmc_ictl 0x02 + #define ICTL_FIFO 0x10 + #define ICTL_ARBIT 0x20 + #define ICTL_SEL 0x40 + #define ICTL_CD 0x80 + #define ICTL_ALLINT (ICTL_ARBIT | ICTL_CD | ICTL_SEL) + #define tmc_astat 0x02 + #define ASTAT_INT 0x01 + #define ASTAT_ARBIT 0x02 + #define ASTAT_PARERR 0x04 + #define ASTAT_SCSIRST 0x08 + #define ASTAT_STATMASK 0x0f + #define ASTAT_FIFODIR 0x10 + #define ASTAT_FIFOEN 0x20 + #define ASTAT_PARENB 0x40 + #define ASTAT_BUSEN 0x80 + + #define tmc_ssctl 0x03 + #define SSCTL_FSYNCHEN 0x40 + #define SSCTL_SYNCHEN 0x80 + #define tmc_fstat 0x03 + + #define tmc_fctl 0x04 + #define FCTL_CLRFIFO 0x01 + #define FCTL_ARBIT 0x04 + #define FCTL_PARENB 0x08 + #define FCTL_INTEN 0x10 + #define FCTL_CLRINT 0x20 + #define FCTL_FIFOW 0x40 + #define FCTL_FIFOEN 0x80 + #define tmc_icnd 0x04 + + #define tmc_mctl 0x05 + #define tmc_idlsb 0x05 + + #define tmc_idmsb 0x06 + + #define tmc_wlb 0x07 + #define tmc_rlb 0x07 + + #define tmc_scsiid 0x08 + #define tmc_sdna 0x08 + + #define tmc_istat 0x09 + #define ISTAT_INTEN 0x08 + #define ISTAT_FIFO 0x10 + #define ISTAT_ARBIT 0x20 + #define ISTAT_SEL 0x40 + #define ISTAT_CD 0x80 + + #define tmc_cfg1 0x0a + + #define tmc_ioctl 0x0b + #define tmc_cfg2 0x0b + + #define tmc_wfifo 0x0c + #define tmc_rfifo 0x0c + + #define tmc_fdcnt 0x0e + + /* Information transfer phases */ + #define BUSFREE_PHASE 0x00 + #define DATA_OUT_PHASE (BSTAT_BSY) + #define DATA_IN_PHASE (BSTAT_BSY|BSTAT_IO) + #define COMMAND_PHASE (BSTAT_CMD|BSTAT_BSY) + #define STATUS_PHASE (BSTAT_CMD|BSTAT_BSY|BSTAT_IO) + #define MESSAGE_OUT_PHASE (BSTAT_CMD|BSTAT_MSG|BSTAT_BSY) + #define MESSAGE_IN_PHASE (BSTAT_CMD|BSTAT_MSG|BSTAT_BSY|BSTAT_IO) + + #define PHASE_RESELECTED (BSTAT_SEL|BSTAT_IO) + + #define PHASE_MASK 0x2f + #define RESEL_PHASE_MASK 0x2e + + /* chip type */ + #define TMCCHIP_UNK 0x00 + #define TMCCHIP_1800 0x01 + #define TMCCHIP_18C50 0x02 + #define TMCCHIP_18C30 0x03 + + #define STGIOSZ 0x10 + + #endif /* !_TMC18C30REG_H_ */ Index: PAO/sys/i386/scsi/tmc18c30/tmc18c30var.h diff -c /dev/null PAO/sys/i386/scsi/tmc18c30/tmc18c30var.h:1.1.8.1 *** /dev/null Fri Dec 25 10:51:31 1998 --- PAO/sys/i386/scsi/tmc18c30/tmc18c30var.h Sun Dec 6 07:48:47 1998 *************** *** 0 **** --- 1,59 ---- + /* $NetBSD$ */ + /* $Id: tmc18c30var.h,v 1.1.8.1 1998/12/05 22:48:47 itojun Exp $ */ + /* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1996 NetBSD/pc98 porting staff. + * Copyright (c) 1996 Naofumi HONDA. + * Copyright (c) 1996 Kouichi Matsuda. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _TMC18C30VAR_H_ + #define _TMC18C30VAR_H_ + + /* softc */ + struct stg_softc { + SCSI_LOW_SOFTC + + u_int sc_chip; + + u_int sc_fsz; + u_int8_t sc_fcb; + + u_int8_t sc_fcWinit; + u_int8_t sc_fcRinit; + + u_int8_t sc_fcsp; + u_int8_t sc_icinit; + u_int8_t sc_busc; + }; + + #ifdef __NetBSD__ + int stgprobe __P((struct device *, struct device *, void *)); + void stgattach __P((struct device *, struct device *, void *)); + #endif + int stgprint __P((void *, char *)); + #endif /* !_TMC18C30VAR_H_ */ Index: PAO/sys/kern/init_main.c diff -c PAO/sys/kern/init_main.c:1.1.1.3 PAO/sys/kern/init_main.c:1.1.1.3.4.1 *** PAO/sys/kern/init_main.c:1.1.1.3 Fri Jul 24 19:20:53 1998 --- PAO/sys/kern/init_main.c Sun Dec 6 07:48:50 1998 *************** *** 68,73 **** --- 68,76 ---- #include #include #include + #ifdef NECMG + #include + #endif /* NECMG */ extern struct linker_set sysinit_set; /* XXX */ *************** *** 490,495 **** --- 493,504 ---- #ifdef BOOTP bootpc_init(); #endif + + #ifdef NECMG + while ( ! necmg_pccard_enabled) + tsleep(& necmg_pccard_enabled, PUSER | PCATCH, "ATA mount", 0); + #endif /* NECMG */ + /* Mount the root file system. */ if ((*mountroot)(mountrootvfsops)) panic("cannot mount root"); Index: PAO/sys/kern/kern_shutdown.c diff -c PAO/sys/kern/kern_shutdown.c:1.1.1.2 PAO/sys/kern/kern_shutdown.c:1.1.1.2.4.2 *** PAO/sys/kern/kern_shutdown.c:1.1.1.2 Fri Jul 24 19:21:04 1998 --- PAO/sys/kern/kern_shutdown.c Tue Dec 22 17:27:59 1998 *************** *** 118,123 **** --- 118,124 ---- */ static sle_p shutdown_list1; static sle_p shutdown_list2; + static sle_p shutdown_list3; static void dumpsys(void); *************** *** 249,254 **** --- 250,263 ---- } splhigh(); if (howto & RB_HALT) { + if (howto & RB_POWEROFF) { + ep = shutdown_list3; + while (ep) { + shutdown_list3 = ep->next; + (*ep->function)(howto, ep->arg); + ep = ep->next; + } + } printf("\n"); printf("The operating system has halted.\n"); printf("Please press any key to reboot.\n\n"); *************** *** 420,425 **** --- 429,437 ---- break; case SHUTDOWN_POST_SYNC: epp = &shutdown_list2; + break; + case SHUTDOWN_POWER_OFF: + epp = &shutdown_list3; break; default: printf("bad exit callout list specified\n"); Index: PAO/sys/necmg/boot/biosboot/Makefile diff -c /dev/null PAO/sys/necmg/boot/biosboot/Makefile:1.1.4.1 *** /dev/null Fri Dec 25 10:51:42 1998 --- PAO/sys/necmg/boot/biosboot/Makefile Sun Dec 6 07:48:53 1998 *************** *** 0 **** --- 1,135 ---- + # $Id: Makefile,v 1.1.4.1 1998/12/05 22:48:53 itojun Exp $ + # + + PROG= boot + + # Order is very important on the SRCS line for this prog + ORGDIR=../../../i386/boot/biosboot + SRCS= start.S table.c boot2.S boot.c asm.S bios.S serial.S + SRCS+= probe_keyboard.c io.c disk.c sys.c + + NOOBJS= + CLEANFILES= start.S table.c boot2.S boot.c asm.S bios.S serial.S + CLEANFILES+= probe_keyboard.c disk.c sys.c + + BINDIR= /usr/mdec + BINMODE= 444 + CFLAGS= -O2 -malign-functions=0 -malign-jumps=0 -malign-loops=0 \ + -mno-486 \ + -DDO_BAD144 -DBOOTWAIT=${BOOTWAIT} -DTIMEOUT=${TIMEOUT} + CFLAGS+= -DBOOTSEG=${BOOTSEG} -DBOOTSTACK=${BOOTSTACK} + CFLAGS+= -I${.CURDIR}/../../.. + CFLAGS+= -DNECMG -I$(ORGDIR) + CFLAGS+= ${CWARNFLAGS} + + # By default, if a serial port is going to be used as console, use COM1 + # (aka /dev/ttyd0). + BOOT_COMCONSOLE_PORT?=0x3F8 + CFLAGS+= -DCOMCONSOLE=${BOOT_COMCONSOLE_PORT} + + BOOT_COMCONSOLE_SPEED?=9600 + CFLAGS+= -DCONSPEED=${BOOT_COMCONSOLE_SPEED} + + # Enable code to take the default boot string from a fixed location on the + # disk. See nextboot(8) and README.386BSD for more info. + #CFLAGS+= -DNAMEBLOCK + #CFLAGS+= -DNAMEBLOCK_WRITEBACK + + # Bias the conversion from the BIOS drive number to the FreeBSD unit number + # for hard disks. This may be useful for people booting in a mixed IDE/SCSI + # environment (set BOOT_HD_BIAS to the number of IDE drives). + #CFLAGS+= -DBOOT_HD_BIAS=1 + # + # Details: this only applies if BOOT_HD_BIAS > 0. If the BIOS drive number + # for the boot drive is >= BOOT_HD_BIAS, then the boot drive is assumed to + # be SCSI and have unit number (BIOS_drive_number - BOOT_HD_BIAS). E.g., + # BOOT_HD_BIAS=1 makes BIOS drive 1 correspond to 1:sd(0,a) instead of + # 1:wd(1,a). If `sd' is given explicitly, then the drive is assumed to be + # SCSI and have BIOS drive number (sd_unit_number + BOOT_HD_BIAS). E.g., + # BOOT_HD_BIAS=1 makes sd(0,a) correspond to 1:sd(0,a) instead of 0:sd(0,a). + + CLEANFILES+= boot.nohdr boot.strip boot1 boot2 sizetest + LDFLAGS+= -N -T 0 -nostdlib + #LINKS= ${BINDIR}/sdboot ${BINDIR}/wdboot\ + # ${BINDIR}/sdboot ${BINDIR}/fdboot\ + # ${BINDIR}/bootsd ${BINDIR}/bootwd\ + # ${BINDIR}/bootsd ${BINDIR}/bootfd + NOSHARED= YES + NOMAN= + STRIP= + + # tunable timeout parameter, waiting for keypress, calibrated in ms + BOOTWAIT?= 5000 + # tunable timeout during string input, calibrated in ms + #TIMEOUT?= 30000 + + # Location that boot2 is loaded at + BOOTSEG= 0x1000 + + # Offset in BOOTSEG for the top of the stack, keep this 16 byte aligned + BOOTSTACK= 0xFFF0 + + boot.strip: boot + cp -p boot boot.strip + strip boot.strip + size boot.strip + + boot.nohdr: boot.strip + dd if=boot.strip of=boot.nohdr ibs=32 skip=1 obs=1024b + ls -l boot.nohdr + + boot1: boot.nohdr + dd if=boot.nohdr of=boot1 bs=512 count=1 + + boot2: boot.nohdr + dd if=boot.nohdr of=boot2 bs=512 skip=1 + @dd if=boot2 skip=14 of=sizetest 2> /dev/null + @if [ -s sizetest ] ; then \ + echo "boot2 is too big" >&2 ; \ + rm boot2 ; \ + exit 2 ; \ + fi + + all: boot1 boot2 + + install: + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ + boot1 ${DESTDIR}${BINDIR}/boot1 + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ + boot2 ${DESTDIR}${BINDIR}/boot2 + for i in sd fd wd od vn ; do \ + ( cd ${DESTDIR}${BINDIR} ; \ + rm -f boot$${i} $${i}boot ; \ + ln -s boot1 $${i}boot ; \ + ln -s boot2 boot$${i} ; ) \ + done + + install-boothelp: + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ + ${.CURDIR}/boot.help ${DESTDIR}/ + + start.S: $(ORGDIR)/start.S + cp -p $(ORGDIR)/start.S . + table.c: $(ORGDIR)/table.c + cp -p $(ORGDIR)/table.c . + boot2.S: $(ORGDIR)/boot2.S + cp -p $(ORGDIR)/boot2.S . + boot.c: $(ORGDIR)/boot.c + cp -p $(ORGDIR)/boot.c . + asm.S: $(ORGDIR)/asm.S + cp -p $(ORGDIR)/asm.S . + bios.S: $(ORGDIR)/bios.S + cp -p $(ORGDIR)/bios.S . + serial.S: $(ORGDIR)/serial.S + cp -p $(ORGDIR)/serial.S . + probe_keyboard.c: $(ORGDIR)/probe_keyboard.c + cp -p $(ORGDIR)/probe_keyboard.c . + #io.c: $(ORGDIR)/io.c + # cp -p $(ORGDIR)/io.c . + disk.c: $(ORGDIR)/disk.c + cp -p $(ORGDIR)/disk.c . + sys.c: $(ORGDIR)/sys.c + cp -p $(ORGDIR)/sys.c . + + .include + .include Index: PAO/sys/necmg/boot/biosboot/io.c diff -c /dev/null PAO/sys/necmg/boot/biosboot/io.c:1.1.4.1 *** /dev/null Fri Dec 25 10:51:42 1998 --- PAO/sys/necmg/boot/biosboot/io.c Sun Dec 6 07:48:55 1998 *************** *** 0 **** --- 1,287 ---- + /* + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * from: Mach, Revision 2.2 92/04/04 11:35:57 rpd + * $Id: io.c,v 1.1.4.1 1998/12/05 22:48:55 itojun Exp $ + */ + + #include "boot.h" + #include + #include + + #define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ + #define K_STATUS 0x64 /* keyboard status */ + #define K_CMD 0x64 /* keybd ctlr command (write-only) */ + + #define K_OBUF_FUL 0x01 /* output buffer full */ + #define K_IBUF_FUL 0x02 /* input buffer full */ + + #define KC_CMD_WIN 0xd0 /* read output port */ + #define KC_CMD_WOUT 0xd1 /* write output port */ + #define KB_A20 0xdf /* enable A20, + enable output buffer full interrupt + enable data line + enable clock line */ + + + static int getchar(int in_buf); + + /* + * Gate A20 for high memory + */ + void + gateA20(void) + { + #if defined(IBM_L40) | defined(NECMG) + outb(0x92, 0x2); + #else IBM_L40 + while (inb(K_STATUS) & K_IBUF_FUL); + while (inb(K_STATUS) & K_OBUF_FUL) + (void)inb(K_RDWR); + + outb(K_CMD, KC_CMD_WOUT); + while (inb(K_STATUS) & K_IBUF_FUL); + outb(K_RDWR, KB_A20); + while (inb(K_STATUS) & K_IBUF_FUL); + #endif IBM_L40 + } + + /* printf - only handles %d as decimal, %c as char, %s as string */ + + void + printf(const char *format, ...) + { + int *dataptr = (int *)&format; + char c; + + dataptr++; + while ((c = *format++)) + if (c != '%') + putchar(c); + else + switch (c = *format++) { + case 'd': { + int num = *dataptr++; + char buf[10], *ptr = buf; + if (num<0) { + num = -num; + putchar('-'); + } + do + *ptr++ = '0'+num%10; + while (num /= 10); + do + putchar(*--ptr); + while (ptr != buf); + break; + } + case 'x': { + unsigned int num = *dataptr++, dig; + char buf[8], *ptr = buf; + do + *ptr++ = (dig=(num&0xf)) > 9? + 'a' + dig - 10 : + '0' + dig; + while (num >>= 4); + do + putchar(*--ptr); + while (ptr != buf); + break; + } + case 'c': putchar((*dataptr++)&0xff); break; + case 's': { + char *ptr = (char *)*dataptr++; + while ((c = *ptr++)) + putchar(c); + break; + } + } + } + + void + putchar(int c) + { + if (c == '\n') + putchar('\r'); + if (loadflags & RB_DUAL) { + putc(c); + serial_putc(c); + } else if (loadflags & RB_SERIAL) + serial_putc(c); + else + putc(c); + } + + static int + getchar(int in_buf) + { + int c; + + loop: + if (loadflags & RB_DUAL) { + if (ischar()) + c = getc(); + else if (serial_ischar()) + c = serial_getc(); + else + goto loop; + } else if (loadflags & RB_SERIAL) + c = serial_getc(); + else + c = getc(); + if (c == '\r') + c = '\n'; + if (c == '\b') { + if (in_buf != 0) { + putchar('\b'); + putchar(' '); + } else { + goto loop; + } + } + putchar(c); + return(c); + } + + /* + * This routine uses an inb to an unused port, the time to execute that + * inb is approximately 1.25uS. This value is pretty constant across + * all CPU's and all buses, with the exception of some PCI implentations + * that do not forward this I/O adress to the ISA bus as they know it + * is not a valid ISA bus address, those machines execute this inb in + * 60 nS :-(. + * + * XXX this should be converted to use bios_tick. + */ + void + delay1ms(void) + { + int i = 800; + while (--i >= 0) + (void)inb(0x84); + } + + static __inline int + isch(void) + { + int isc; + + /* + * Checking the keyboard has the side effect of enabling clock + * interrupts so that bios_tick works. Check the keyboard to + * get this side effect even if we only want the serial status. + */ + isc = ischar(); + + if (loadflags & RB_DUAL) { + if (isc != 0) + return (isc); + } else if (!(loadflags & RB_SERIAL)) + return (isc); + return (serial_ischar()); + } + + static __inline unsigned + pword(unsigned physaddr) + { + unsigned result; + + /* + * Give the fs prefix separately because gas omits it for + * "movl %fs:0x46c, %eax". + */ + __asm __volatile("fs; movl %1, %0" : "=r" (result) + : "m" (*(unsigned *)physaddr)); + return (result); + } + + int + gets(char *buf) + { + #define bios_tick pword(0x46c) + #define BIOS_TICK_MS 55 + unsigned initial_bios_tick; + char *ptr=buf; + + #if BOOTWAIT + for (initial_bios_tick = bios_tick; + bios_tick - initial_bios_tick < BOOTWAIT / BIOS_TICK_MS;) + #endif + if (isch()) + for (;;) { + switch(*ptr = getchar(ptr - buf) & 0xff) { + case '\n': + case '\r': + *ptr = '\0'; + return 1; + case '\b': + if (ptr > buf) ptr--; + continue; + default: + ptr++; + } + #if TIMEOUT + 0 + #if !BOOTWAIT + #error "TIMEOUT without BOOTWAIT" + #endif + for (initial_bios_tick = bios_tick;;) { + if (isch()) + break; + if (bios_tick - initial_bios_tick >= + TIMEOUT / BIOS_TICK_MS) + return 0; + } + #endif + } + return 0; + } + + int + strcmp(const char *s1, const char *s2) + { + while (*s1 == *s2) { + if (!*s1++) + return 0; + s2++; + } + return 1; + } + + void + bcopy(const char *from, char *to, int len) + { + while (len-- > 0) + *to++ = *from++; + } + + /* To quote Ken: "You are not expected to understand this." :) */ + + void + twiddle(void) + { + putchar((char)tw_chars); + tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24); + putchar('\b'); + } Index: PAO/sys/necmg/conf/Makefile.necmg diff -c /dev/null PAO/sys/necmg/conf/Makefile.necmg:1.1.4.1 *** /dev/null Fri Dec 25 10:51:43 1998 --- PAO/sys/necmg/conf/Makefile.necmg Sun Dec 6 07:49:00 1998 *************** *** 0 **** --- 1,200 ---- + # Makefile.i386 -- with config changes. + # Copyright 1990 W. Jolitz + # from: @(#)Makefile.i386 7.1 5/10/91 + # $Id: Makefile.necmg,v 1.1.4.1 1998/12/05 22:49:00 itojun Exp $ + # + # Makefile for FreeBSD + # + # This makefile is constructed from a machine description: + # config machineid + # Most changes should be made in the machine description + # /sys/i386/conf/``machineid'' + # after which you should do + # config machineid + # Generic makefile changes should be made in + # /sys/i386/conf/Makefile.i386 + # after which config should be rerun for all machines. + # + + # Which version of config(8) is required. + %VERSREQ= 220000 + + CC?= cc + CPP?= cpp + LD?= /usr/bin/ld + + .if exists(./@/.) + S= ./@ + .else + S= ../.. + .endif + I386= ${S}/i386 + + COPTFLAGS?=-O + INCLUDES= -nostdinc -I- -I. -I$S + # This hack is to allow kernel compiles to succeed on machines w/out srcdist + .if exists($S/../include) + INCLUDES+= -I$S/../include + .else + INCLUDES+= -I/usr/include + .endif + COPTS= ${INCLUDES} ${IDENT} -DKERNEL + CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS} + LOAD_ADDRESS?= F0100000 + .if defined(PROF) + CFLAGS+= -malign-functions=4 + .if ${PROFLEVEL} >= 2 + IDENT+= -DGPROF4 -DGUPROF + PROF+= -mprofiler-epilogue + .endif + .endif + + NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $< + NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< + # XXX LOCORE means "don't declare C stuff" not "for locore.s". + NORMAL_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< + DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $< + DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< + DRIVER_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< + PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< + + SYSTEM_CFILES= ioconf.c param.c vnode_if.c config.c + SYSTEM_SFILES= ${I386}/i386/locore.s + SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o config.o + SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} + SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ + SYSTEM_LD= @${LD} -Bstatic -Z -T ${LOAD_ADDRESS} -o $@ -X ${SYSTEM_OBJS} vers.o + .if ${CFLAGS:M-g} == "" + SYMORDER_EXCLUDE=-x symbols.exclude + .endif + SYSTEM_LD_TAIL= @echo rearranging symbols; \ + symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \ + size $@; chmod 755 $@ + + %BEFORE_DEPEND + + %OBJS + + %CFILES + + %SFILES + + %LOAD + + %CLEAN + + clean: + rm -f *.o *.s eddep errs genassym kernel linterrs \ + makelinks param.c symbols.exclude symbols.sort tags \ + vers.c vnode_if.c vnode_if.h ${CLEAN} + + #lint: /tmp param.c + # @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ + # ${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \ + # grep -v 'struct/union .* never defined' | \ + # grep -v 'possible pointer alignment problem' + + symbols.exclude: Makefile + echo "gcc2_compiled." >symbols.exclude + echo "___gnu_compiled_c" >>symbols.exclude + + symbols.sort: ${I386}/i386/symbols.raw + grep -v '^#' ${I386}/i386/symbols.raw \ + | sed 's/^ //' | sort -u > symbols.sort + + locore.o: ${I386}/i386/locore.s assym.s + ${NORMAL_S} + + # everything potentially depends on the Makefile since everything potentially + # depends on the options. Some things are more dependent on the Makefile for + # historical reasons. + machdep.o: Makefile + + # the following is necessary because autoconf.o depends on #if GENERIC + autoconf.o: Makefile + + # XXX - may no longer be needed + locore.o: Makefile + + # depends on KDB (cons.o also depends on GENERIC) + trap.o cons.o: Makefile + + # this rule stops ./assym.s in .depend from causing problems + ./assym.s: assym.s + + assym.s: genassym + ./genassym >assym.s + + # Some of the defines that genassym outputs may well depend on the + # value of kernel options. + genassym.o: ${I386}/i386/genassym.c Makefile + ${CC} -c ${CFLAGS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c + + genassym: genassym.o + ${CC} ${CFLAGS} ${PARAM} genassym.o -o $@ + + # XXX this assumes that the options for NORMAL_C* and DRIVER_C* are identical. + depend: assym.s param.c vnode_if.h ${BEFORE_DEPEND} + rm -f ./machine ; ln -s ${I386}/include ./machine + rm -f .newdep + mkdep -a -f .newdep ${COPTS} ${CFILES} ${SYSTEM_CFILES} + mkdep -a -f .newdep ${COPTS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c + MKDEP_CPP="${CPP}" ; export MKDEP_CPP ; \ + mkdep -a -f .newdep -DLOCORE ${COPTS} ${SFILES} ${SYSTEM_SFILES} + rm -f .depend + mv -f .newdep .depend + + links: + egrep '#if' ${CFILES:Nswapkernel.c} | sed -f $S/conf/defines | \ + sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink + echo ${CFILES:Nswapkernel.c} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ + sort -u | comm -23 - dontlink | \ + sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks + sh makelinks && rm -f dontlink + + tags: + @echo "see $S/kern/Makefile for tags" + + install: + @if [ ! -f kernel ] ; then \ + echo "You must first build your kernel before trying to install." ; \ + exit 1 ; \ + fi + .if exists(${DESTDIR}/kernel) + chflags noschg ${DESTDIR}/kernel + mv ${DESTDIR}/kernel ${DESTDIR}/kernel.old + .endif + PATH=$${PATH}:/sbin:/usr/sbin; \ + if [ `sysctl -n kern.bootfile` = ${DESTDIR}/kernel ] ; then \ + sysctl -w kern.bootfile=${DESTDIR}/kernel.old ; \ + if [ -f /var/db/kvm_kernel.db ] ; then \ + mv -f /var/db/kvm_kernel.db /var/db/kvm_kernel.old.db ; \ + fi \ + fi + install -c -m 555 -o root -g wheel -fschg kernel ${DESTDIR}/ + + ioconf.o: ioconf.c $S/sys/param.h $S/sys/buf.h \ + ${I386}/isa/isa_device.h ${I386}/isa/isa.h ${I386}/isa/icu.h + ${CC} -c ${CFLAGS} ioconf.c + + param.c: $S/conf/param.c + -rm -f param.c + cp $S/conf/param.c . + + param.o: param.c Makefile + ${CC} -c ${CFLAGS} ${PARAM} param.c + + vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} + sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT} + ${CC} ${CFLAGS} -c vers.c + + vnode_if.c: $S/kern/vnode_if.sh $S/kern/vnode_if.src + sh $S/kern/vnode_if.sh $S/kern/vnode_if.src + vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src + sh $S/kern/vnode_if.sh $S/kern/vnode_if.src + + .include + + %RULES + + # DO NOT DELETE THIS LINE -- make depend uses it Index: PAO/sys/necmg/conf/NECMG diff -c /dev/null PAO/sys/necmg/conf/NECMG:1.1.4.3 *** /dev/null Fri Dec 25 10:51:43 1998 --- PAO/sys/necmg/conf/NECMG Wed Dec 23 10:23:05 1998 *************** *** 0 **** --- 1,109 ---- + # + # Mobile Gear (NECMG) Kernel Configuration + # Shin Takemura takemura@ca2.so-net.ne.jp + # $Id: NECMG,v 1.1.4.3 1998/12/23 01:23:05 hosokawa Exp $ + # + + machine "necmg" + cpu "I386_CPU" + cpu "I486_CPU" + cpu "I586_CPU" + #cpu "I686_CPU" + ident NECMG + maxusers 6 + + options NECMG #NEC Mobile Gear + options NECMG_ZOOMCONS + options MAXCONS=4 + + options MATH_EMULATE #Support for x87 emulation + options INET #InterNETworking + options FFS #Berkeley Fast Filesystem + #options NFS #Network Filesystem + #options MFS #Memory Filesystem + options MSDOSFS #MSDOS Filesystem + #options "CD9660" #ISO 9660 Filesystem + options PROCFS #Process filesystem + options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] + options UCONSOLE #Allow users to grab the console + options FAILSAFE #Be conservative + #options USERCONFIG #boot -c editor + #options VISUAL_USERCONFIG #visual boot -c editor + + # If your laptop have not had Windoze95-Ready BIOS, please update it. + # Such old BIOS'es sometimes have critical bugs at 32-bit protected + # mode APM BIOS interface (which have not used by Windoze 3.1). + + # PC-card suspend/resume support (experimental) + #options APM_PCCARD_RESUME + options PCIC_RESUME_RESET + + # Keep power for serial cards when the system suspends + # (If your machine hangs up when you try to suspend the system with + # FAX/Modem PCMCIA card, uncomment this option). + #options SIO_SUSP_KEEP_PWR + + # Suspend the system when the battery status is "Low" + #options "APM_BATT_LOW_SUSPEND" + + # If you want to use NTP on laptop machines, uncomment the following + # option. Current APM implementation affects NTP client. + #options "APM_NO_CLOCK_ADJUST" + + # Some X-servers cannot survive suspend/resume on laptop. + # This option kicks her when the system is resumed from suspended mode. + #options SYSCONS_VTY_RESUME + + + config kernel root on wd0 + + controller isa0 + + # Dont remove these two lines! + pseudo-device card 1 + + device pcic0 at isa? port 0x3e0 irq 11 vector pcicintr + + controller wdc0 at isa? disable port "IO_WD1" bio irq 14 vector wdintr + disk wd0 at wdc0 drive 0 + + # syscons is the default console driver, resembling an SCO console + device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr + + # Mandatory, don't remove + device npx0 at isa? port "IO_NPX" flags 0x1 irq 13 vector npxintr + + # + # Laptop support (see LINT for more options) + # + device apm0 at isa? # Advanced Power Management + options APM_BROKEN_STATCLOCK # Workaround some buggy APM BIOS + + device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr + device sio1 at isa? port "IO_COM3" tty irq 9 vector siointr + + pseudo-device loop + pseudo-device log + pseudo-device sl 1 + # DHCP uses BPF (Berkeley Packet Filter) + #pseudo-device bpfilter 4 + # ijppp uses tun instead of ppp device + #pseudo-device ppp 1 + #pseudo-device vn 1 + pseudo-device tun 1 + pseudo-device pty 16 + pseudo-device gzip # Exec gzipped a.out's + + #options DDB + + # KTRACE enables the system-call tracing facility ktrace(2). + # This adds 4 KB bloat to your kernel, and slightly increases + # the costs of each syscall. + #options KTRACE #kernel tracing + + # This provides support for System V shared memory. + # + options SYSVSHM + options SYSVSEM + options SYSVMSG + Index: PAO/sys/necmg/conf/devices.necmg diff -c /dev/null PAO/sys/necmg/conf/devices.necmg:1.1.4.1 *** /dev/null Fri Dec 25 10:51:43 1998 --- PAO/sys/necmg/conf/devices.necmg Sun Dec 6 07:49:03 1998 *************** *** 0 **** --- 1,18 ---- + # This file tells what major numbers the various possible swap devices have. + # + # $Id: devices.necmg,v 1.1.4.1 1998/12/05 22:49:03 itojun Exp $ + # + wd 0 + dk 1 + fd 2 + wt 3 + sd 4 + st 5 + cd 6 + mcd 7 + vn 15 + scd 16 + pcd 17 + wcd 19 + od 20 + wfd 21 Index: PAO/sys/necmg/conf/files.necmg diff -c /dev/null PAO/sys/necmg/conf/files.necmg:1.1.4.1 *** /dev/null Fri Dec 25 10:51:44 1998 --- PAO/sys/necmg/conf/files.necmg Sun Dec 6 07:49:06 1998 *************** *** 0 **** --- 1,310 ---- + # This file tells config what files go into building a kernel, + # files marked standard are always included. + # + # $Id: files.necmg,v 1.1.4.1 1998/12/05 22:49:06 itojun Exp $ + # + aicasm optional ahc device-driver \ + dependency "$S/dev/aic7xxx/*.[chyl]" \ + compile-with "make -f $S/dev/aic7xxx/Makefile MAKESRCPATH=$S/dev/aic7xxx" \ + no-obj no-implicit-rule \ + clean "aicasm" + # + aic7xxx_{seq,reg}.h optional ahc device-driver \ + compile-with "./aicasm ${INCLUDES} -o aic7xxx_seq.h -r aic7xxx_reg.h $S/dev/aic7xxx/aic7xxx.seq" \ + no-obj no-implicit-rule before-depend \ + clean "aic7xxx_seq.h aic7xxx_reg.h" \ + dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} aicasm" + # + linux_genassym optional compat_linux \ + dependency "$S/i386/linux/linux_genassym.c $S/i386/linux/linux.h" \ + compile-with "${CC} ${CFLAGS} ${PARAM} -UKERNEL -o $@ $<" \ + no-obj no-implicit-rule \ + clean "linux_genassym" + # + linux_assym.h optional compat_linux \ + dependency "linux_genassym" \ + compile-with "./linux_genassym > $@" \ + no-obj no-implicit-rule before-depend \ + clean "linux_assym.h" + # + i386/scsi/93cx6.c optional ahc device-driver + i386/apm/apm.c optional apm device-driver + #i386/apm/apm_setup.s optional apm + i386/eisa/3c5x9.c optional ep device-driver + i386/eisa/aic7770.c optional ahc device-driver \ + dependency "aic7xxx_reg.h $S/i386/eisa/aic7770.c" + i386/eisa/aha1742.c optional ahb device-driver + i386/eisa/bt74x.c optional bt device-driver + i386/eisa/dpt_eisa.c optional dpt device-driver + i386/eisa/eisaconf.c optional eisa + i386/eisa/if_vx_eisa.c optional vx device-driver + i386/eisa/if_fea.c optional fea device-driver + i386/i386/autoconf.c standard device-driver + i386/i386/busdma_machdep.c standard + i386/i386/cons.c standard + i386/i386/db_disasm.c optional ddb + i386/i386/db_interface.c optional ddb + i386/i386/db_trace.c optional ddb + i386/i386/i386-gdbstub.c optional ddb + i386/i386/exception.s standard + i386/i386/identcpu.c standard + i386/i386/in_cksum.c optional inet + i386/i386/initcpu.c standard + # locore.s needs to be handled in Makefile to put it first. Otherwise it's + # now normal. + # i386/i386/locore.s standard + i386/i386/machdep.c standard + i386/i386/math_emulate.c optional math_emulate + i386/i386/mem.c standard + i386/i386/microtime.s standard + i386/i386/perfmon.c optional perfmon profiling-routine + i386/i386/perfmon.c optional perfmon + i386/i386/pmap.c standard + i386/i386/procfs_machdep.c standard + i386/i386/support.s standard + i386/i386/swtch.s standard + i386/i386/sys_machdep.c standard + i386/i386/trap.c standard + i386/i386/userconfig.c optional userconfig + i386/i386/vm_machdep.c standard + i386/ibcs2/ibcs2_fcntl.c optional ibcs2 + i386/ibcs2/ibcs2_stat.c optional ibcs2 + i386/ibcs2/ibcs2_ipc.c optional ibcs2 + i386/ibcs2/ibcs2_msg.c optional ibcs2 + i386/ibcs2/ibcs2_misc.c optional ibcs2 + i386/ibcs2/ibcs2_other.c optional ibcs2 + i386/ibcs2/ibcs2_signal.c optional ibcs2 + i386/ibcs2/ibcs2_ioctl.c optional ibcs2 + i386/ibcs2/ibcs2_socksys.c optional ibcs2 + i386/ibcs2/ibcs2_sysi86.c optional ibcs2 + i386/ibcs2/ibcs2_util.c optional ibcs2 + i386/ibcs2/ibcs2_isc.c optional ibcs2 + i386/ibcs2/ibcs2_isc_sysent.c optional ibcs2 + i386/ibcs2/ibcs2_xenix.c optional ibcs2 + i386/ibcs2/ibcs2_xenix_sysent.c optional ibcs2 + i386/ibcs2/ibcs2_errno.c optional ibcs2 + i386/ibcs2/ibcs2_sysent.c optional ibcs2 + i386/ibcs2/ibcs2_sysvec.c optional ibcs2 + i386/ibcs2/imgact_coff.c optional ibcs2 + i386/isa/aha1542.c optional aha device-driver + i386/isa/aic6360.c optional aic device-driver + i386/isa/b004.c optional bqu device-driver + i386/isa/bt5xx-445.c optional bt device-driver + i386/isa/clock.c standard + i386/isa/cronyx.c optional cx device-driver + i386/isa/ctx.c optional ctx device-driver + i386/isa/cx.c optional cx device-driver + i386/isa/cy.c optional cy device-driver + i386/isa/diskslice_machdep.c standard + i386/isa/elink.c optional ep device-driver + i386/isa/elink.c optional ie device-driver + i386/isa/fd.c optional fd device-driver + i386/isa/ft.c optional ft device-driver + i386/isa/gpib.c optional gp device-driver + i386/isa/asc.c optional asc device-driver + i386/isa/gsc.c optional gsc device-driver + i386/isa/hss.c optional hss device-driver + i386/isa/if_ar.c optional ar device-driver + i386/isa/if_cnw.c optional cnw device-driver + i386/isa/if_cs.c optional cs device-driver + i386/isa/if_cx.c optional cx device-driver + i386/isa/if_ed.c optional ed device-driver + i386/isa/if_eg.c optional eg device-driver + i386/isa/if_el.c optional el device-driver + i386/isa/if_ep.c optional ep device-driver + i386/isa/if_ex.c optional ex device-driver + i386/isa/if_fe.c optional fe device-driver + i386/isa/if_ie.c optional ie device-driver + i386/isa/if_le.c optional le device-driver + i386/isa/if_lnc.c optional lnc device-driver + i386/isa/if_sn.c optional sn device-driver + i386/isa/if_sr.c optional sr device-driver + i386/isa/if_wl.c optional wl device-driver + i386/isa/if_wlp.c optional wlp device-driver + i386/isa/if_ze.c optional ze device-driver + i386/isa/if_zp.c optional zp device-driver + i386/isa/isa.c optional isa device-driver + i386/isa/istallion.c optional stli device-driver + i386/isa/joy.c optional joy device-driver + #i386/isa/kbdio.c optional psm device-driver + #i386/isa/kbdio.c optional sc device-driver + #i386/isa/kbdio.c optional vt device-driver + i386/isa/lpt.c optional lpt device-driver + i386/isa/labpc.c optional labpc device-driver + i386/isa/mcd.c optional mcd device-driver + i386/isa/mse.c optional mse device-driver + i386/isa/ncr5380.c optional nca device-driver + i386/isa/npx.c optional npx device-driver + i386/isa/pcaudio.c optional pca device-driver + i386/isa/matcd/matcd.c optional matcd device-driver + i386/isa/pcibus.c optional pci device-driver + i386/isa/pcicx.c optional ze device-driver + i386/isa/pcicx.c optional zp device-driver + i386/isa/pcvt/pcvt_drv.c optional vt device-driver + i386/isa/pcvt/pcvt_ext.c optional vt device-driver + i386/isa/pcvt/pcvt_kbd.c optional vt device-driver + i386/isa/pcvt/pcvt_out.c optional vt device-driver + i386/isa/pcvt/pcvt_sup.c optional vt device-driver + i386/isa/pcvt/pcvt_vtf.c optional vt device-driver + i386/isa/pnp.c optional pnp device-driver + i386/isa/prof_machdep.c optional profiling-routine + i386/isa/psm.c optional psm device-driver + i386/isa/qcam.c optional qcam device-driver + i386/isa/qcamio.c optional qcam device-driver + i386/isa/random_machdep.c standard + i386/isa/rc.c optional rc device-driver + i386/isa/scc.c optional scc device-driver + i386/isa/scc_subr.c optional scc device-driver + i386/isa/scd.c optional scd device-driver + i386/isa/seagate.c optional sea device-driver + i386/isa/si.c optional si device-driver + i386/isa/si2_z280.c optional si device-driver + i386/isa/si3_t225.c optional si device-driver + i386/isa/sio.c optional sio device-driver + i386/isa/snd/sound.c optional pcm device-driver + i386/isa/snd/dmabuf.c optional pcm device-driver + i386/isa/snd/ad1848.c optional pcm device-driver + i386/isa/snd/sb_dsp.c optional pcm device-driver + i386/isa/snd/clones.c optional pcm device-driver + i386/isa/sound/dev_table.c optional snd device-driver + i386/isa/sound/soundcard.c optional snd device-driver + i386/isa/sound/sound_switch.c optional snd device-driver + i386/isa/sound/audio.c optional snd device-driver + i386/isa/sound/dmabuf.c optional snd device-driver + i386/isa/sound/sys_timer.c optional snd device-driver + i386/isa/sound/sequencer.c optional snd device-driver + i386/isa/sound/patmgr.c optional snd device-driver + i386/isa/sound/adlib_card.c optional opl device-driver + i386/isa/sound/opl3.c optional opl device-driver + i386/isa/sound/gus_card.c optional gus device-driver + i386/isa/sound/gus_midi.c optional gus device-driver + i386/isa/sound/gus_vol.c optional gus device-driver + i386/isa/sound/gus_wave.c optional gus device-driver + i386/isa/sound/ics2101.c optional gus device-driver + i386/isa/sound/sound_timer.c optional gus device-driver + i386/isa/sound/midi_synth.c optional gus device-driver + i386/isa/sound/midibuf.c optional gus device-driver + i386/isa/sound/ad1848.c optional gusxvi device-driver + i386/isa/sound/ad1848.c optional gus device-driver + i386/isa/sound/ad1848.c optional mss device-driver + i386/isa/sound/midi_synth.c optional mss device-driver + i386/isa/sound/midibuf.c optional mss device-driver + i386/isa/sound/mpu401.c optional mpu device-driver + i386/isa/sound/midi_synth.c optional mpu device-driver + i386/isa/sound/midibuf.c optional mpu device-driver + i386/isa/sound/pas2_card.c optional pas device-driver + i386/isa/sound/pas2_midi.c optional pas device-driver + i386/isa/sound/pas2_mixer.c optional pas device-driver + i386/isa/sound/pas2_pcm.c optional pas device-driver + i386/isa/sound/midi_synth.c optional pas device-driver + i386/isa/sound/midibuf.c optional pas device-driver + i386/isa/sound/sb_card.c optional sb device-driver + i386/isa/sound/sb_dsp.c optional sb device-driver + i386/isa/sound/sb_midi.c optional sb device-driver + i386/isa/sound/sb_mixer.c optional sb device-driver + i386/isa/sound/midi_synth.c optional sb device-driver + i386/isa/sound/midibuf.c optional sb device-driver + i386/isa/sound/sb16_dsp.c optional sbxvi device-driver + i386/isa/sound/sb16_midi.c optional sbmidi device-driver + i386/isa/sound/uart6850.c optional uart device-driver + i386/isa/sound/midi_synth.c optional uart device-driver + i386/isa/sound/midibuf.c optional uart device-driver + i386/isa/sound/trix.c optional trix device-driver + i386/isa/sound/sscape.c optional sscape device-driver + i386/isa/sound/awe_wave.c optional awe device-driver + i386/isa/spc.c optional spc device-driver + i386/isa/spigot.c optional spigot device-driver + i386/isa/spkr.c optional speaker device-driver + i386/isa/stallion.c optional stl device-driver + i386/isa/syscons.c optional sc device-driver + i386/isa/tw.c optional tw device-driver + i386/isa/ultra14f.c optional uha device-driver + i386/isa/wd.c optional wdc device-driver + i386/isa/wd.c optional wd device-driver + i386/isa/atapi.c optional atapi device-driver + i386/isa/wcd.c optional wcd device-driver + i386/isa/wd7000.c optional wds device-driver + i386/isa/wt.c optional wt device-driver + i386/isa/wfd.c optional wfd device-driver + i386/linux/imgact_linux.c optional compat_linux + i386/linux/linux_dummy.c optional compat_linux + i386/linux/linux_file.c optional compat_linux + i386/linux/linux_ioctl.c optional compat_linux + i386/linux/linux_ipc.c optional compat_linux + i386/linux/linux_locore.s optional compat_linux \ + dependency "linux_assym.h" + i386/linux/linux_misc.c optional compat_linux + i386/linux/linux_signal.c optional compat_linux + i386/linux/linux_socket.c optional compat_linux + i386/linux/linux_stats.c optional compat_linux + i386/linux/linux_sysent.c optional compat_linux + i386/linux/linux_sysvec.c optional compat_linux + i386/linux/linux_util.c optional compat_linux + i386/scsi/aic7xxx.c optional ahc device-driver \ + dependency "aic7xxx_{reg,seq}.h" + i386/scsi/bt.c optional bt device-driver + i386/scsi/ncr53c500/ncr53c500.c optional ncv device-driver + i386/scsi/ncr53c500/ncr53c500if.c optional ncv device-driver + i386/scsi/tmc18c30/tmc18c30.c optional stg device-driver + i386/scsi/tmc18c30/tmc18c30if.c optional stg device-driver + i386/scsi/scsi_low/scsi_low.c optional scsi_low + i386/scsi/scsi_low/scsi_low_pisa.c optional scsi_low + libkern/bcd.c standard + libkern/divdi3.c standard + libkern/inet_ntoa.c standard + libkern/index.c standard + libkern/mcount.c optional profiling-routine + libkern/moddi3.c standard + libkern/qdivrem.c standard + libkern/qsort.c standard + libkern/random.c standard + libkern/scanc.c standard + libkern/skpc.c standard + libkern/strcat.c standard + libkern/strcmp.c standard + libkern/strcpy.c standard + libkern/strlen.c standard + libkern/strncmp.c standard + libkern/strncpy.c standard + libkern/udivdi3.c standard + libkern/umoddi3.c standard + gnu/i386/fpemul/div_small.s optional gpl_math_emulate + gnu/i386/fpemul/errors.c optional gpl_math_emulate + gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate + gnu/i386/fpemul/fpu_aux.c optional gpl_math_emulate + gnu/i386/fpemul/fpu_entry.c optional gpl_math_emulate + gnu/i386/fpemul/fpu_etc.c optional gpl_math_emulate + gnu/i386/fpemul/fpu_trig.c optional gpl_math_emulate + gnu/i386/fpemul/get_address.c optional gpl_math_emulate + gnu/i386/fpemul/load_store.c optional gpl_math_emulate + gnu/i386/fpemul/poly_2xm1.c optional gpl_math_emulate + gnu/i386/fpemul/poly_atan.c optional gpl_math_emulate + gnu/i386/fpemul/poly_div.s optional gpl_math_emulate + gnu/i386/fpemul/poly_l2.c optional gpl_math_emulate + gnu/i386/fpemul/poly_mul64.s optional gpl_math_emulate + gnu/i386/fpemul/poly_sin.c optional gpl_math_emulate + gnu/i386/fpemul/poly_tan.c optional gpl_math_emulate + gnu/i386/fpemul/polynomial.s optional gpl_math_emulate + gnu/i386/fpemul/reg_add_sub.c optional gpl_math_emulate + gnu/i386/fpemul/reg_compare.c optional gpl_math_emulate + gnu/i386/fpemul/reg_constant.c optional gpl_math_emulate + gnu/i386/fpemul/reg_div.s optional gpl_math_emulate + gnu/i386/fpemul/reg_ld_str.c optional gpl_math_emulate + gnu/i386/fpemul/reg_mul.c optional gpl_math_emulate + gnu/i386/fpemul/reg_norm.s optional gpl_math_emulate + gnu/i386/fpemul/reg_round.s optional gpl_math_emulate + gnu/i386/fpemul/reg_u_add.s optional gpl_math_emulate + gnu/i386/fpemul/reg_u_div.s optional gpl_math_emulate + gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate + gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate + gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate + gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate + gnu/i386/isa/dgb.c optional dgb device-driver + gnu/i386/isa/nic3008.c optional nic device-driver + gnu/i386/isa/nic3009.c optional nnic device-driver + pci/wd82371.c optional wd device-driver + necmg/necmg/necmg_apm.c standard + necmg/necmg/necmg_cons.c standard + necmg/necmg/necmg_fonts.c standard + necmg/necmg/necmg_icon.c standard + necmg/isa/kbdio.c optional sc device-driver Index: PAO/sys/necmg/conf/majors.necmg diff -c /dev/null PAO/sys/necmg/conf/majors.necmg:1.1.4.1 *** /dev/null Fri Dec 25 10:51:44 1998 --- PAO/sys/necmg/conf/majors.necmg Sun Dec 6 07:49:07 1998 *************** *** 0 **** --- 1,137 ---- + $Id: majors.necmg,v 1.1.4.1 1998/12/05 22:49:07 itojun Exp $ + + Hopefully, this list will one day be obsoleted by DEVFS, but for now + this is the current allocation of device major numbers. + + For local use, you are encouraged to use the reserved numbers. + + If you intend the driver to be available, send email to the + hackers@freebsd.org mailing list to see about having a number + reserved for you. + + The most "complete" version of this will be the one in FreeBSD-current. + (see http://www.freebsd.org/ or from ftp://ftp.cdrom.com/pub/FreeBSD/) + + blkdev name comments + 0 wd ST506 disk controller (with IDE extensions) + 1 wfd ATAPI Floppy client of "ata" + 2 fd floppy disk + 3 wt QIC-02/36 tape + 4 sd SCSI "disk" type + 5 st SCSI "tape" type + 6 cd SCSI "cdrom" type + 7 mcd Mitsumi CDROM interface + 8 lkm assigned to Loadable Kernel modules + 9 lkm assigned to Loadable Kernel modules + 10 lkm assigned to Loadable Kernel modules + 11 lkm assigned to Loadable Kernel modules + 12 lkm assigned to Loadable Kernel modules + 13 lkm assigned to Loadable Kernel modules + 14 ?? reserved for local use + 15 vn vnode disk device + 16 scd Sony CDROM interface + 17 matcd Matsushita/Panasonic/Creative(SB) CDROM interface + 18 ata "device independent" ATA/IDE driver + 19 wcdb ATAPI CDROM client of "ata" + 20 od SCSI "magneto-optical" disk + 21 ccd concatenated disk + 22 gd Geometry disk. + 23 worm SCSI "worm type" + 24 ?? (wstb in 3.x) + 25 ?? (vinum RAID fs in 3.x) + 26 sw VM internal swap device + chrdev name comments + 0 cn console + 1 ctty /dev/tty + 2 mm /dev/mem,kmem,etc + 3 wd ST506 disk controller (with IDE extensions) + 4 swap /dev/drum + 5 pts pseudo tty "tty" half + 6 ptc pseudo tty "master" half + 7 log system log + 8 bqu B004 transputer board + 9 fd floppy disk + 10 wt QIC-02/36 tape + 11 spigot Video capture? + 12 sc syscons/pcvt virtual consoles + 13 sd SCSI "disk type" + 14 st SCSI "tape type" + 15 cd SCSI "CDROM type" + 16 lpt PC parallel printer port + 17 ch SCSI changer + 18 su SCSI universal type + 19 tw X-10 power interface + 20 ?? reserved for local use + 21 psm PS/2 Mouse + 22 fd (/dev/stdin etc) + 23 bpf Berkeley Packet Filter + 24 pca PC speaker (/dev/pcaudio) + 25 ?? was vat + 26 spkr PC speaker (/dev/spkr) + 27 mse Microsoft bus-mouse + 28 sio 16450/16550 serial + 29 mcd Mitsumi CDROM interface + 30 snd sound driver system + 31 uk SCSI "unknown device type" + 32 lkmc Loadable Kernel Module Controller + 33 lkm assigned to Loadable Kernel Modules + 34 lkm assigned to Loadable Kernel Modules + 35 lkm assigned to Loadable Kernel Modules + 36 lkm assigned to Loadable Kernel Modules + 37 lkm assigned to Loadable Kernel Modules + 38 lkm assigned to Loadable Kernel Modules + 39 apm Advanced Power Management + 40 ctx Cortex + 41 ?? was socksys + 42 cx Cronyx + 43 vn vnode "disk" device + 44 gp GPIB + 45 scd Sony CDROM interface + 46 matcd Matsushita/Panasonic/Creative(SB) CDROM interface + 47 gsc Genius Scanner + 48 cy Cyclades + 49 ssc SCSI super device + 50 card pcmcia cards + 51 joy joystick + 52 tun IP tunnel device + 53 snp tty snoop + 54 OLDnic ISDN system + 55 OLDisdn ISDN system + 56 OLDity ISDN system + 57 OLDitel ISDN system + 58 dgb Digiboard + 59 OLDispy ISDN system + 60 OLDnnic ISDN system + 61 pt SCSI "processor type" + 62 worm SCSI "worm type" + 63 rc Riscom/8 driver + 64 ?? Talisman + 65 sctarg SCSI target + 66 labpc National Instruments LabPC + 67 meteor Matrox Meteor video capture + 68 si Specialix SI/XIO (peter@freebsd.org) + 69 wcd ATAPI CDROM client of "ata" + 70 od SCSI "magneto-optical disk type" + 71 asc AmiScan driver + 72 stl Stallion (cd1400 based) (gerg@stallion.oz.au) + 73 qcam quickcam + 74 ccd concatenated disk + 75 stli Stallion (intelligent cdk based) (gerg@stallion.oz.au) + 76 scc IBM Smart Capture Card (ohashi@mickey.ai.kyutech.ac.jp) + 77 cyy Cyclades Ye/PCI serial card + 78 pci PCI bus + 79 ipl IP Filter + 80 xdcp Assigned to Chris Ficklin + 81 ?? RocketPort/Steve Gericke + 82 ppi Generic Parallel I/O + 83 hss Hitachi microcomputer system Speech Synthesizer card (itojun@itojun.org) + 87 wfd ATAPI floppy client of "ata" + 88 dpt DPT RAID Controller + 89 pps Pulse-Per-Second timing interface + 90 wst ATAPI tape client of "ata" + 91 vinum RAID fs + 92 bktr Bt848 video capture driver (hasty@star-gate.com) + 93 coda CODA filesystem. + 94 loran Loran-C Receiver + 95 gd Geometry disk + 96 altq alternate queueing (including cbq, red, wfq) Index: PAO/sys/necmg/conf/options.necmg diff -c /dev/null PAO/sys/necmg/conf/options.necmg:1.1.4.1 *** /dev/null Fri Dec 25 10:51:44 1998 --- PAO/sys/necmg/conf/options.necmg Sun Dec 6 07:49:10 1998 *************** *** 0 **** --- 1,102 ---- + # $Id: options.necmg,v 1.1.4.1 1998/12/05 22:49:10 itojun Exp $ + BOUNCEPAGES opt_bounce.h + USER_LDT + MATH_EMULATE opt_math_emulate.h + GPL_MATH_EMULATE opt_math_emulate.h + + IBCS2 opt_dontuse.h + COMPAT_LINUX opt_dontuse.h + + SHOW_BUSYBUFS opt_machdep.h + PANIC_REBOOT_WAIT_TIME opt_machdep.h + MAXMEM opt_machdep.h + PERFMON opt_perfmon.h + AUTO_EOI_1 opt_auto_eoi.h + AUTO_EOI_2 opt_auto_eoi.h + BREAK_TO_DEBUGGER opt_comconsole.h + COMCONSOLE opt_comconsole.h + CONADDR opt_comconsole.h + CONUNIT opt_comconsole.h + CONSPEED opt_comconsole.h + COM_ESP opt_sio.h + COM_MULTIPORT opt_sio.h + DSI_SOFT_MODEM opt_sio.h + I586_CTR_GUPROF opt_i586_guprof.h + I586_PMC_GUPROF opt_i586_guprof.h + WLCACHE opt_wavelan.h + WLDEBUG opt_wavelan.h + + AHC_TAGENABLE opt_aic7xxx.h + AHC_SCBPAGING_ENABLE opt_aic7xxx.h + AHC_ALLOW_MEMIO opt_aic7xxx.h + AHC_SHARE_SCBS opt_aic7xxx.h + + CLK_CALIBRATION_LOOP opt_clock.h + CLK_USE_I8254_CALIBRATION opt_clock.h + CLK_USE_I586_CALIBRATION opt_clock.h + + NO_F00F_HACK opt_cpu.h + CPU_BLUELIGHTNING_FPU_OP_CACHE opt_cpu.h + CPU_BLUELIGHTNING_3X opt_cpu.h + CPU_BTB_EN opt_cpu.h + CPU_DISABLE_5X86_LSSER opt_cpu.h + CPU_FASTER_5X86_FPU opt_cpu.h + CPU_I486_ON_386 opt_cpu.h + CPU_IORT opt_cpu.h + CPU_LOOP_EN opt_cpu.h + CPU_RSTK_EN opt_cpu.h + CPU_SUSP_HLT opt_cpu.h + CPU_UPGRADE_HW_CACHE opt_cpu.h + CYRIX_CACHE_WORKS opt_cpu.h + CYRIX_CACHE_REALLY_WORKS opt_cpu.h + I386_CPU opt_cpu.h + I486_CPU opt_cpu.h + I586_CPU opt_cpu.h + I686_CPU opt_cpu.h + + SC_SPLASH_SCREEN opt_syscons.h + MAXCONS opt_syscons.h + SLOW_VGA opt_syscons.h + SC_HISTORY_SIZE opt_syscons.h + SC_DISABLE_REBOOT opt_syscons.h + SC_BAD_FLICKER opt_syscons.h + + PSM_HOOKAPM opt_psm.h + PSM_RESETAFTERSUSPEND opt_psm.h + PSM_DEBUG opt_psm.h + + KBD_RESETDELAY opt_kbdio.h + KBD_MAXRETRY opt_kbdio.h + KBD_MAXWAIT opt_kbdio.h + KBDIO_DEBUG opt_kbdio.h + + ATAPI opt_atapi.h + ATAPI_STATIC opt_atapi.h + + CMD640 opt_wd.h + + USERCONFIG opt_userconfig.h + VISUAL_USERCONFIG opt_userconfig.h + USERCONFIG_BOOT opt_userconfig.h + + EISA_SLOTS opt_eisa.h + + FDC_DEBUG opt_fdc.h + FDC_PRINT_BOGUS_CHIPTYPE opt_fdc.h + + # pcvt(4) has a bunch of options + FAT_CURSOR opt_pcvt.h + XSERVER opt_pcvt.h + PCVT_24LINESDEF opt_pcvt.h + PCVT_CTRL_ALT_DEL opt_pcvt.h + PCVT_EMU_MOUSE opt_pcvt.h + PCVT_FREEBSD opt_pcvt.h + PCVT_META_ESC opt_pcvt.h + PCVT_NSCREENS opt_pcvt.h + PCVT_PRETTYSCRNS opt_pcvt.h + PCVT_SCANSET opt_pcvt.h + PCVT_SCREENSAVER opt_pcvt.h + PCVT_USEKBDSEC opt_pcvt.h + PCVT_VT220KEYB opt_pcvt.h + + NECMG_ZOOMCONS opt_necmg.h Index: PAO/sys/necmg/isa/kbdio.c diff -c /dev/null PAO/sys/necmg/isa/kbdio.c:1.1.4.1 *** /dev/null Fri Dec 25 10:51:45 1998 --- PAO/sys/necmg/isa/kbdio.c Sun Dec 6 07:49:12 1998 *************** *** 0 **** --- 1,193 ---- + /*- + * Copyright (c) 1996 Shin Takemura All rights reserved. + * + * This code is derived from i386/isa/kdbio.c. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: kbdio.c,v 1.1.4.1 1998/12/05 22:49:12 itojun Exp $ + */ + #ifdef NECMG + #include "sc.h" + #include "vt.h" + #include "psm.h" + #include "opt_kbdio.h" + + #include + #include + #include + #include + #include + #include + #include + + /* I/O recovery time */ + #define KBDC_DELAYTIME 20 + #define KBDD_DELAYTIME 7 + + #ifndef max + #define max(x,y) ((x) > (y) ? (x) : (y)) + #endif + #define kbdcp(p) ((struct kbdc_softc *)(p)) + + #define NKBDC max(NSC, NVT) + + struct kbdc_softc { + int port; /* base port address */ + int lock; /* FIXME: XXX not quite a semaphore... */ + }; + + static struct kbdc_softc kbdc_softc[NKBDC] = { { 0 }, }; + + /* + * associate a port number with a KBDC + */ + KBDC + kbdc_open(int port) + { + int s; + int i; + + s = spltty(); + for (i = 0; i < NKBDC; ++i) { + if (kbdc_softc[i].port == port) { + splx(s); + return (KBDC) &kbdc_softc[i]; + } + if (kbdc_softc[i].port <= 0) { + kbdc_softc[i].port = port; + kbdc_softc[i].lock = FALSE; + splx(s); + return (KBDC) &kbdc_softc[i]; + } + } + splx(s); + return NULL; + } + + /* + * I/O access arbitration in `kbdio' + * + * The `kbdio' module uses a simplistic convention to arbitrate + * I/O access to the controller/keyboard/mouse. The convention requires + * close cooperation of the calling device driver. + * + * The device driver which utilizes the `kbdio' module are assumed to + * have the following set of routines. + * a. An interrupt handler (the bottom half of the driver). + * b. Timeout routines which may briefly polls the keyboard controller. + * c. Routines outside interrupt context (the top half of the driver). + * They should follow the rules below: + * 1. The interrupt handler may assume that it always has full access + * to the controller/keyboard/mouse. + * 2. The other routines must issue `spltty()' if they wish to + * prevent the interrupt handler from accessing + * the controller/keyboard/mouse. + * 3. The timeout routines and the top half routines of the device driver + * arbitrate I/O access by observing the lock flag in `kbdio'. + * The flag is manipulated via `kbdc_lock()'; when one wants to + * perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if + * the call returns with TRUE. Otherwise the caller must back off. + * Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion + * is finished. This mechanism does not prevent the interrupt + * handler from being invoked at any time and carrying out I/O. + * Therefore, `spltty()' must be strategically placed in the device + * driver code. Also note that the timeout routine may interrupt + * `kbdc_lock()' called by the top half of the driver, but this + * interruption is OK so long as the timeout routine observes the + * the rule 4 below. + * 4. The interrupt and timeout routines should not extend I/O operation + * across more than one interrupt or timeout; they must complete + * necessary I/O operation within one invokation of the routine. + * This measns that if the timeout routine acquires the lock flag, + * it must reset the flag to FALSE before it returns. + */ + + /* set/reset polling lock */ + int + kbdc_lock(KBDC p, int lock) + { + int prevlock; + + prevlock = kbdcp(p)->lock; + kbdcp(p)->lock = lock; + + return (prevlock != lock); + } + + /* check if any data is waiting to be processed */ + int + kbdc_data_ready(KBDC p) + { + return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & 0x40); + } + + static void + read_kbd_data_done(struct kbdc_softc *kbdc) + { + unsigned char d; + d = inb(kbdc->port + KBD_STATUS_PORT); + outb(kbdc->port + KBD_STATUS_PORT, (d | 0x80)); + DELAY(KBDC_DELAYTIME); + outb(kbdc->port + KBD_STATUS_PORT, d); + DELAY(KBDC_DELAYTIME); + } + + /* read one byte from the keyboard */ + int + read_kbd_data(KBDC p) + { + /* CPU will stay inside the loop for 200msec at most */ + struct kbdc_softc *kbdc = kbdcp(p); + int retry = 10000; + int port = kbdc->port; + int d; + + while ((d = inb(port + KBD_DATA_PORT)) == 0) { + DELAY(KBDD_DELAYTIME); + if (--retry < 0) + return -1; /* timeout */ + } + read_kbd_data_done(kbdc); + return (d); + } + + /* read one byte from the keyboard, but return immediately if + * no data is waiting + */ + int + read_kbd_data_no_wait(KBDC p) + { + int c; + + c = inb(kbdcp(p)->port + KBD_DATA_PORT); + if (c == 0) { + return (-1); /* no data */ + } else { + read_kbd_data_done(kbdcp(p)); + return (c); + } + } + #endif /* NECMG */ Index: PAO/sys/necmg/necmg/necmg.h diff -c /dev/null PAO/sys/necmg/necmg/necmg.h:1.1.4.2 *** /dev/null Fri Dec 25 10:51:45 1998 --- PAO/sys/necmg/necmg/necmg.h Tue Dec 22 17:28:00 1998 *************** *** 0 **** --- 1,90 ---- + /* + * NEC Mobile Gear header file + * + * Copyright (c) 1998 Shin Takemura all rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: necmg.h,v 1.1.4.2 1998/12/22 08:28:00 nakagawa Exp $ + * + */ + #define NECMG_COM1 1 + #define NECMG_COM2 2 + #define NECMG_COM3 3 + #define NECMG_COM4 4 + #define NECMG_IO_COM1 0x3f8 + #define NECMG_IO_COM3 0x3e8 + + #ifdef KERNBASE + /* We need these header files. + * #include + * #include + * #include + */ + #define NECMG_PA_TO_VA(pa) (KERNBASE + (pa)) + #define NECMG_FRAMEBUFFER ((unsigned char*)NECMG_PA_TO_VA(0xB0000)) + #endif + #define NECMG_FB_SIZE 0x10000 + #define NECMG_WHITE 0x00 + #define NECMG_LIGHTGRAY 0x55 + #define NECMG_DARKGRAY 0xaa + #define NECMG_BLACK 0xff + + #define NECMG_ICON8x8_NONE 0 + #define NECMG_ICON8x8_NUM 1 + #define NECMG_ICON8x8_CAPS 2 + #define NECMG_ICON8x8_KANA 3 + #define NECMG_ICON8x8_ZOOM 4 + #define NECMG_ICON8x8_SCRL 5 + + struct necmg_font_s { + unsigned char *data; + int width, height, nchars; + }; + extern struct necmg_font_s necmg_fonts[]; + + void necmg_apm_init __P((void)); + int necmg_apm_int __P((u_long *eax, u_long *ebx, u_long *ecx)); + int necmg_set_contrast(int high_low); + void necmg_draw_char(int x, int y, int code, int atr, int size); + int necmg_com_power(int port, int on); + void necmg_cpu_poweroff(int howto, void *dummy_arg); + struct slot; + int necmg_pccard_enabler(struct slot *sp); + + void necmg_cons_update(int xsize, int ysize, + unsigned short *vvram, int start, int end); + void necmg_cons_clear(void); + int necmg_cons_get_zoompos(void); + int necmg_cons_set_zoompos(int xsize, int ysize, unsigned short *vvram, int y); + + void necmg_draw_icon(int x, int y, unsigned char *icon, + int width, int height, + unsigned char fore, unsigned char back); + + extern unsigned char necmg_icon16x8[][32]; + extern unsigned char necmg_icon8x8[][16]; + extern unsigned char *necmg_fontrom_base; + extern int necmg_pccard_enabled; Index: PAO/sys/necmg/necmg/necmg_apm.c diff -c /dev/null PAO/sys/necmg/necmg/necmg_apm.c:1.1.4.2 *** /dev/null Fri Dec 25 10:51:45 1998 --- PAO/sys/necmg/necmg/necmg_apm.c Tue Dec 22 17:28:02 1998 *************** *** 0 **** --- 1,888 ---- + /*- + * NEC Mobile Gear APM (Advanced Power Management) + * + * Copyright (c) 1998 Shin Takemura all rights reserved. + * Copyright (c) 1998 Kenji Ohta all rights reserved. + * Copyright (c) 1998 NAKAGAWA, Yoshihisa all rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: necmg_apm.c,v 1.1.4.2 1998/12/22 08:28:02 nakagawa Exp $ + * + */ + #ifdef NECMG + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #include + #include + #include + #include + + #include "card.h" + + static void necmg_apm_timeout __P((void *dummy)); + static int check_power_keys __P((void)); + static void check_power_status __P((void)); + static void register_disp __P((void)); + + static int set_serial_power(int on); + static int set_modem_power(int on); + + static int mg_suspend __P((void)); + static void in22(unsigned char idx, unsigned char *data); + static void out22(unsigned char idx, unsigned char data); + static void in28(unsigned char idx, unsigned char *data); + static void out28(unsigned char idx, unsigned char data); + static int waitfor(unsigned char mask, unsigned short port, + int flag, int timeout); + static int write_readF18(unsigned short cmd, unsigned short *data); + static int readF18(unsigned char *data, int n); + static int writeF18(unsigned char *data, int n); + static int outF18(unsigned char data); + static int inF18(unsigned char *data); + + #define TIMEOUT 0x4000 + #define TIMER_INTERVAL (hz / 20) /* about 50 msec */ + #define MSEC 1000 + #define NECMG_BATT_UNKNOWN 255 + #define NECMG_BATT_TYPE1 1 + #define NECMG_BATT_TYPE2 2 + #define NECMG_ACLINE_UNKNOWN 255 + #define NECMG_ACLINE_OFFLINE 0 + #define NECMG_ACLINE_ONLINE 1 + #define NECMG_BATTLEVEL_UNKNOWN 255 + #define NECMG_BATTSTAT_UNKNOWN 255 + #define NECMG_BATTSTAT_HIGH 0 + #define NECMG_BATTSTAT_LOW 1 + #define NECMG_BATTSTAT_CRITICAL 2 + #define NECMG_BATTLIFE_UNKNOWN 255 + + #define NECMG_BATTLEVEL_NICONS 6 + #define NECMG_ACONLINE_ICON 1 + #define NECMG_BATTLEVEL_ICON 2 + + /* + * These values are experimental. + */ + #define NECMG_BATTLEVEL_FULL 0xe8 + #define NECMG_BATTLEVEL_HIGH 0xd4 + #define NECMG_BATTLEVEL_LOW 0xc3 + #define NECMG_BATTLEVEL_CRITICAL 0xc0 + + static unsigned char ac_line = NECMG_ACLINE_UNKNOWN; + static int batt_type = NECMG_BATT_UNKNOWN; + static unsigned char batt_level = NECMG_BATTLEVEL_UNKNOWN; + static unsigned char batt_stat = NECMG_BATTSTAT_UNKNOWN; + static int blink = 0; + + /* + * global variables (Thsy comes from apm_setup.s) + */ + u_long apm_version; + u_long apm_cs_entry; + u_short apm_cs32_base; + u_short apm_cs16_base; + u_short apm_ds_base; + u_short apm_cs_limit; + u_short apm_ds_limit; + u_short apm_flags; + u_short kernelbase; + + /* + #define NECMG_APM_DEBUG + */ + + /* static data */ + struct necmg_apm_softc { + int dummy; + }; + static struct necmg_apm_softc necmg_apm_softc; + static initialized = 0; + static int event_suspend = 0; + static int event_battlow = 0; + static int serial_power = 1; /* When system boot up + COM1 power is already ON. */ + static int modem_power = 0; + + void + necmg_apm_init() + { + if (initialized) + return; + + necmg_apm_timeout(NULL); + + initialized = 1; + return; + } + + static void + necmg_apm_timeout(void *dummy) + { + struct necmg_apm_softc *sc = &necmg_apm_softc; + static int tick = 0; + + #ifdef NECMG_APM_DEBUG + register_disp(); + #endif + check_power_keys(); + if ((tick++ % (hz/TIMER_INTERVAL)) == 0) { + /* Once per second, may be. */ + blink++; + check_power_status(); + } + + timeout(necmg_apm_timeout, NULL, TIMER_INTERVAL); + } + + /* + * Fake BIOS entry point. + */ + int + necmg_apm_int(u_long *eax, u_long *ebx, u_long *ecx) + { + static int mg_resumed = 0; + + if (*eax == ((APM_BIOS << 8) | APM_SETPWSTATE) && + *ebx == PMDV_ALLDEV && *ecx == PMST_SUSPEND) { + /* + * SUSPEND + */ + #ifdef NECMG_APM_DEBUG + printf("fake APM BIOS: go suspend\n"); + #endif + mg_suspend(); + mg_resumed = 1; + return 0; + } else + if (*eax == ((APM_BIOS << 8) | APM_GETPWSTATUS) && + *ebx == PMDV_ALLDEV && *ecx == 0) { + /* + * GET POWER STATUS + */ + *ebx = (ac_line << 8) | batt_stat; + *ecx = NECMG_BATTLIFE_UNKNOWN; + /*#ifdef NECMG_APM_DEBUG + */ + #if 1 + printf("necmg power status: type=%d level=%02x\n", + batt_type, batt_level); + #endif + return 0; + } else + if (*eax == ((APM_BIOS << 8) | APM_GETPMEVENT)) { + /* + * GET PM EVENT + */ + if (mg_resumed) { + *ebx = PMEV_NORMRESUME; + mg_resumed = 0; + } else + if (event_suspend) { + *ebx = PMEV_USERSUSPENDREQ; + event_suspend = 0; + } else + if (event_battlow) { + *ebx = PMEV_BATTERYLOW; + event_battlow = 0; + } else { + *ebx = PMEV_NOEVENT; + } + return 0; + } + return 1; + } + + /* + * Power off + */ + void + necmg_cpu_poweroff(int howto, void *dummy_arg) { + printf("\nGood bye!\n"); + /* wait 1 sec for printf's to complete and be read */ + DELAY(1000000); + + /* + * I don't know why this cause system power off. + * But it works fine on MC-MK12. (takemura) + */ + + /* force a shutdown by unmapping entire address space ! */ + bzero((caddr_t) PTD, PAGE_SIZE); + + /* "good night, sweet prince .... " */ + invltlb(); + /* NOTREACHED */ + while(1); + } + + int + necmg_set_contrast(int high_low) + { + int s, res; + unsigned char cmd[2][8] = { + { 0x70, 0x76, 0x70, 0x74, 0x70, 0x76, 0x70, 0x77 }, + { 0x70, 0x72, 0x70, 0x70, 0x70, 0x72, 0x70, 0x77 } + }; + + s = splimp(); + outb(0xf11, 0x02); + outb(0xf11, 0x00); + outb(0xf11, 0x80); + + res = writeF18(cmd[high_low ? 1 : 0], 8); + + outb(0xf11, 0x02); + outb(0xf11, 0x00); + splx(s); + + return (res); + } + + static void + register_disp() + { + int x = 100; + unsigned char d0, d1, d2; + static unsigned db0 = 0, db1 = 0, db2 = 0; + char *p, buf[100]; + + d0 = inb(0xf12); + d1 = inb(0xf15); + d2 = inb(0xf18); + + if (d0 == db0 && d1 == db1 && d2 == db2) { + return; + } + sprintf(buf, "%02x %02x %02x", d0, d1, d2); + + db0 = d0; + db1 = d1; + db2 = d2; + for (p = buf; *p; p++) { + necmg_draw_char(x, 0, *p & 0xff, 7, 8); + x += 2; + } + } + + /*----------------------------------------------------------------------------- + + COM port power control + + -----------------------------------------------------------------------------*/ + int + necmg_com_power(int port, int on) + { + #ifdef NECMG_APM_DEBUG + printf("COM%d %s\n", port, on ? "on" : "off"); + #endif + switch(port) { + case NECMG_COM1: + serial_power = on; + return (set_serial_power(on)); + break; + case NECMG_COM3: + modem_power = on; + return (set_modem_power(on)); + default: + panic("necmg_com_power(): invalied port"); + } + return (0); + } + + static int + set_serial_power(int on) + { + disable_intr(); + /* + if (res = COM1Power_check_bx(bx)) { + return (res); + } + */ + if (on) { + /* Power ON */ + outb(0xf02, inb(0xf02) | 0x80); + outb(0xf15, inb(0xf15) & ~0x01); + DELAY(120 * MSEC); + outb(0xf12, inb(0xf12) & ~0x08); /* COM1 on */ + DELAY(70 * MSEC); + outb(0xf08, (inb(0xf08) & 0xfa) | 0x2); + } else { + /* Power OFF */ + outb(0xf08, inb(0xf08) & 0xf8); + outb(0xf12, inb(0xf12) | 0x08); /* COM1 off */ + /* XXX, This makes system hungup. + outb(0xf15, inb(0xf15) | 0x01); + */ + DELAY(85 * MSEC); + } + enable_intr(); + return (0); + } + + static int + set_modem_power(int on) + { + int sound; + disable_intr(); + if (on) { + if ((inb(0xf12) & 0x10) == 0) return (0); + outb(0xf14, inb(0xf14) & 0xdf); + + sound = !(inb(0xf12) & 0x4); /* Sound on/off ? */ + outb(0xf12, (inb(0xf12) & ~0x20) | 0x10 | 0x4); /* modem, sound off */ + DELAY(10 * MSEC); + + outb(0xf12, inb(0xf12) & 0xef); /* Modem on */ + DELAY(200 * MSEC); + + outb(0xf12, inb(0xf12) | 0x20); /* 0x20 ??? off ? */ + DELAY(10 * MSEC); + + /* Sound ON/OFF restore */ + if (sound) { + outb(0xf12, inb(0xf12) & ~0x04); /* sound ON */ + } + + /* + * very very long wait. + */ + /* XXX, I can't stand this. + DELAY(2500 * MSEC); + */ + DELAY(2000 * MSEC); + } else { + sound = !(inb(0xf12) & 0x04); + outb(0xf12, inb(0xf12) | 0x04); /* sound off */ + + outb(0xf12, inb(0xf12) & ~0x20); /* ??? on ?*/ + DELAY(10 * MSEC); + + if (sound) { + outb(0xf12, inb(0xf12) & ~0x04); /* sound on */ + } + outb(0xf12, inb(0xf12) | 0x10); /* modem off */ + } + enable_intr(); + + return (0); + } + + /*----------------------------------------------------------------------------- + + POWER STATUS + + -----------------------------------------------------------------------------*/ + static void + check_power_status() + { + unsigned char tmpb; + unsigned short tmpw; + + unsigned char level_table[][NECMG_BATTLEVEL_NICONS + 1] = { + /* fatal 0 1 2 3 4 5 */ + { 0xc3, 0xc5, 0xcb, 0xd3, 0xdc, 0xe7, 0xf4 }, /* dry battery */ + /* 0xc3+pow(i,1.6)*2.8 */ + { 0xc0, 0xc3, 0xc7, 0xcd, 0xd4, 0xdc, 0xe4 }, /* cargable battery */ + /* 0xc0+pow(i,1.4)*3 */ + }; + + int pos = 77; + int icon = -1, color; + static int prev_icon = -1; + static int prev_color = -1; + + /* + * AC or battery + */ + in28(0x0d, &tmpb); + if (tmpb & 0x10) { + ac_line = 1; + } else { + ac_line = 0; + } + + /* + * Dry battery or rechargable + */ + if (write_readF18(0x4030, &tmpw) != 0 || + (tmpw & 0xc0f0) != 0xc0f0) { + /* error */ + printf("necmg: write_readF18(battery type) failed.\n"); + } else { + if (tmpw & 0x0008) { + batt_type = NECMG_BATT_TYPE1; + } else { + batt_type = NECMG_BATT_TYPE2; + } + } + + /* + * Battery level + */ + if (write_readF18(0x4050, &tmpw) != 0 || + (tmpw & 0xc0f0) != 0xc0d0) { + /* error */ + printf("necmg: write_readF18(battery level) failed.\n"); + batt_level = NECMG_BATTLEVEL_UNKNOWN; + } else { + batt_level = ((tmpw >> 8) & 0x3f) | ((tmpw<<6) & 0xc0); + if (0xff <= batt_level) { + batt_level = 0xfe; + } + } + + if (batt_level == NECMG_BATTLEVEL_UNKNOWN) { + icon = NECMG_BATTLEVEL_ICON; + color = NECMG_LIGHTGRAY; + batt_stat = NECMG_BATTSTAT_UNKNOWN; + } else { + int level; + unsigned char *table; + if (batt_type == NECMG_BATT_TYPE1) { + /* battery type is type1 */ + table = level_table[0]; + } else { + /* battery type is type2 or unknown */ + table = level_table[1]; + } + + for (level = NECMG_BATTLEVEL_NICONS - 1; -2 < level; level--) { + if (table[level + 1] <= batt_level) break; + } + + if (level < 0) { + icon = NECMG_BATTLEVEL_ICON + 0; + color = (blink % 2) ? NECMG_BLACK : NECMG_WHITE; + batt_stat = NECMG_BATTSTAT_CRITICAL; + if (level < -1) { + /* + * DANGER !! + * battery level is too low. + */ + event_battlow = 1; + } + } else { + icon = NECMG_BATTLEVEL_ICON + level; + color = NECMG_BLACK; + batt_stat = (2 < level) ? NECMG_BATTSTAT_HIGH : NECMG_BATTSTAT_LOW; + } + } + if (ac_line == NECMG_ACLINE_ONLINE) { + /* + * AC line status is online. + */ + if (batt_stat == NECMG_BATTSTAT_HIGH || !(blink % 2)) { + /* + * and battery voltage is green. + */ + icon = NECMG_ACONLINE_ICON; + color = NECMG_BLACK; + } + } + + /* + * Draw power status icon. + */ + if (icon != -1) { + if (prev_icon != icon || prev_color != color || (blink % 20) == 0) { + necmg_draw_icon(pos * 2, 0, + necmg_icon16x8[icon], + 4, 8, color, NECMG_WHITE); + prev_icon = icon; + prev_color = color; + } + } + + #ifdef NECMG_APM_DEBUG + { + int x = 4; + char *p, buf[100]; + unsigned char tmp0, tmp1; + + sprintf(buf, "%s %d %02x %d", + ac_line ? "AC" : " ", + batt_type, + batt_level, + batt_stat); + for (p = buf; *p; p++) { + necmg_draw_char(x, 0, *p & 0xff, 7, 8); + x += 2; + } + } + #endif + } + + /*----------------------------------------------------------------------------- + + POWER KEY + + -----------------------------------------------------------------------------*/ + static int + check_power_keys() + { + int s, i; + unsigned char tmp, data[2]; + + s = splimp(); + if (inb(0xf12) & 0x02) { + splx(s); + return (0); + } + + tmp = inb(0xf15); + for (i = 0; i < 2; i++) { + if (inF18(&data[i])) { + /* timeout */ + outb(0xf15, tmp); + splx(s); + return (0); + } + } + + outb(0xf15, tmp); + splx(s); + + #ifdef NECMG_APM_DEBUG + printf("check_power_key: %02x %02x\n", data[0], data[1]); + #endif + + if ((data[0] & 0xf0) == 0xa0 && (data[1] & 0xc0) == 0xc0) { + if (data[1] & 0x01) { + /* cover switch status changed */ + if ((data[0] & 0x01) == 0) { + /* cover was closed */ + event_suspend = 1; + } + } + if (data[1] & 0x02) { + /* power switch status changed */ + if (data[0] & 0x02) { + /* power key down */ + event_suspend = 1; + } else { + /* power key up */ + } + } + } + + return (0); + } + + /*----------------------------------------------------------------------------- + + POWER MANAGEMENT PROCESSOR I/O ROUTINE + + I/O: + F12h, F15h, F18h, F19h + + -----------------------------------------------------------------------------*/ + static int + write_readF18(unsigned short cmd, unsigned short *data) + { + int s, res; + int errflag; + unsigned char data0, data1; + unsigned char buf[2]; + + s = splimp(); + outb(0xf11, 0x02); + outb(0xf11, 0x00); + outb(0xf11, 0x80); + + buf[0] = (cmd & 0xff); + buf[1] = ((cmd >> 8) & 0xff); + res = writeF18(buf, 2); + if (res) goto exit_func; + + res = readF18(buf, 2); + if (res) goto exit_func; + + exit_func: + outb(0xf15, (inb(0xf15) & 0xf9) | 0x02); + + outb(0xf11, 0x02); + outb(0xf11, 0x00); + splx(s); + + *data = buf[1] * 256 + buf[0]; + + return (res); + } + + static int + readF18(unsigned char *data, int n) + { + int i, res; + int s; + + s = splimp(); + /* + * === Failsafe === + * Usually F19h = 0xff and 0xF15 = -----01- + * so this block is not need. + */ + outb(0xf19, 0xff); + outb(0xf15, (inb(0xf15) & 0xf9) | 0x02); + res = waitfor(0x40, 0xf15, 1, TIMEOUT); + if (res) goto exit_func; + + for (i = 0; i < n; i++) { + res = inF18(&data[i]); + if (res) { + goto exit_func; + } + } + res = 0; + + exit_func: + splx(s); + #ifdef NECMG_APM_DEBUG + printf("readF18(%d bytes) = %d\n", n, res); + #endif + + return (res); + } + + static int + writeF18(unsigned char *data, int n) + { + int i, j, res; + int s; + + s = splimp(); + + outb(0xf19, 0x00); + + for (i = 0; i < n; i += 2) { + outb(0xf15, (inb(0xf15) & 0xf9) | 0x00); + for (j = 1000; 0 < j; j--) { + DELAY(50); + check_power_keys(); + if ((inb(0xf15) & 0x40) == 0) break; + } + if (j <= 0) goto exit_func; + + res = outF18(data[i]); + if (res) goto exit_func; + + res = outF18(data[i + 1]); + if (res) goto exit_func; + + outb(0xf15, (inb(0xf15) & 0xf9) | 0x02); + res = waitfor(0x40, 0xf15, 1, TIMEOUT); + if (res) goto exit_func; + } + + exit_func: + outb(0xf19, 0xff); + outb(0xf15, (inb(0xf15) & 0xf9) | 0x02); + splx(s); + + #ifdef NECMG_APM_DEBUG + printf("writeF18(%d bytes) = %d\n", n, res); + #endif + + return (res); + } + + static int + outF18(unsigned char data) + { + int res; + + outb(0xf18, data); + outb(0xf15, (inb(0xf15) & 0xf9) | 0x04); + res = waitfor(2, 0xf12, 0, TIMEOUT); + if (res) goto exit_func; + outb(0xf15, (inb(0xf15) & 0xf9) | 0x00); + res = waitfor(0x02, 0xf12, 1, TIMEOUT); + + exit_func: + #ifdef NECMG_APM_DEBUG + if (res) { + printf("outF18(%02x): res=%d\n", data, res); + } + #endif + return (res); + } + + static int + inF18(unsigned char *data) + { + int res; + outb(0xf15, (inb(0xf15) & 0xf9) | 0x02); + res = waitfor(2, 0xf12, 0, TIMEOUT); + if (res) goto exit_func; + *data = inb(0xf18); + outb(0xf15, (inb(0xf15) & 0xf9) | 0x06); + res = waitfor(2, 0xf12, 1, TIMEOUT); + + exit_func: + #ifdef NECMG_APM_DEBUG + if (res) { + printf("inF18(): inb(0xf18)=%02x res=%d\n", *data, res); + } + #endif + return (res); + } + + static int + waitfor(unsigned char mask, unsigned short port, int flag, int timeout) + { + int res, t; + unsigned char data; + static count = 0; + + count++; + + for (t = 0; t < timeout; t++) { + DELAY(100); + if (flag) { + if ((data = inb(port)) & mask) { + break; + } + } else { + if (((data = inb(port)) & mask) == 0) { + break; + } + } + } + if (timeout <= t) { + #ifdef NECMG_APM_DEBUG + printf("%d: waitfor(%x, %x, %d, %x): rest=%x inb(%x)=%02x\n", + count, mask, port, flag, timeout, + timeout - t, port, data); + #endif + } + return (t < timeout ? 0 : 1); + } + + /*----------------------------------------------------------------------------- + + SUSPEND / RESUME + + I/O: + 22h, 23h + 28h, 2Ah + + -----------------------------------------------------------------------------*/ + static int + mg_suspend(void) + { + unsigned char tmp0, tmp1; + + disable_intr(); + in22(0x2e, &tmp0); + in22(0x2f, &tmp0); + out22(0x2e, 0x84); + out22(0x2f, 0x50); + + out22(0x2e, tmp0); + out22(0x2f, tmp1); + + in28(0x0a, &tmp0); + out28(0x0a, 0x8f); + + if (serial_power) set_serial_power(0); + if (modem_power) set_modem_power(0); + + /* + * set start up info 0xb. + */ + outb(0x70, 0x8f); + outb(0x71, 0x0b); + + /* + * suspend + */ + out22(0x01, 0x10); + + #if NCARD == 0 + /* + * If we have no pccard service, make ATA flash happy here. + */ + necmg_wd_pccard_enabler(); + #endif /* NCARD */ + + if (serial_power) set_serial_power(1); + if (modem_power) set_modem_power(1); + + enable_intr(); + return 0; + } + + static void + in22(unsigned char idx, unsigned char *data) + { + unsigned char tmp; + tmp = inb(0x22); + outb(0x22, idx); + *data = inb(0x23); + outb(0x22, tmp); + } + + static void + out22(unsigned char idx, unsigned char data) + { + unsigned char tmp; + tmp = inb(0x22); + outb(0x22, idx); + outb(0x23, data); + outb(0x22, tmp); + } + + static void + in28(unsigned char idx, unsigned char *data) + { + unsigned char tmp; + tmp = inb(0x28); + outb(0x28, idx); + *data = inb(0x2a); + outb(0x28, tmp); + } + + static void + out28(unsigned char idx, unsigned char data) + { + unsigned char tmp; + + tmp = inb(0x28); + outb(0x28, idx); + outb(0x2a, data); + outb(0x28, tmp); + } + + #endif /* NECMG */ Index: PAO/sys/necmg/necmg/necmg_cons.c diff -c /dev/null PAO/sys/necmg/necmg/necmg_cons.c:1.1.4.1 *** /dev/null Fri Dec 25 10:51:46 1998 --- PAO/sys/necmg/necmg/necmg_cons.c Sun Dec 6 07:49:20 1998 *************** *** 0 **** --- 1,333 ---- + /*- + * + * Copyright (c) 1998 Shin Takemura all rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: necmg_cons.c,v 1.1.4.1 1998/12/05 22:49:20 itojun Exp $ + * + */ + #ifdef NECMG + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #include + #include + + unsigned char *necmg_fontrom_base = 0; + static mg_zoompos = -1; + + void + necmg_draw_icon(int x, int y, unsigned char *icon, int width, int height, + unsigned char fore, unsigned char back) + { + unsigned char *fb = NECMG_FRAMEBUFFER; + + fb += x + y * 0x100; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + *fb++ = (fore & *icon) | (back & ~*icon); + icon++; + } + fb += (0x100 - width); + } + } + + static unsigned char * + necmg_font_data(int code) + { + static unsigned char null_font8[] = { + 0xfe, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0xfe, 0x00, + }; + static unsigned char null_font16[] = { + 0xff, 0xfe, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, + 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, + 0x80, 0x02, 0x80, 0x02, 0xff, 0xfe, 0x00, 0x00 + }; + + if (code < 0x100) { + /* 1 byte code */ + if (necmg_fontrom_base == 0) + (null_font8); /* kanji ROM not available yet */ + return (necmg_fontrom_base + 0x83800 + code * 16); + } + + /* 2 byte code */ + if (necmg_fontrom_base == 0) (null_font16); /* kanji ROM not available yet */ + return necmg_fontrom_base + + (code & 0x7f00) * 0x0c + + (code & 0x7f) * 0x20 + 0x2b800; + } + + static void + necmg_put_char(int x, int y, int code, int attr) + { + int zoom = (y == mg_zoompos && 0 <= mg_zoompos); + + x = x * 2; + if (mg_zoompos < y && 0 <= mg_zoompos) { + y = y * 9 + 8 + 7; + } else { + y = y * 9 + 8; + } + necmg_draw_char(x, y, code, attr, zoom ? 16 : 9); + } + + /* EUC kanji code + * 2 byte code (variable length code) + */ + #define iskanji1(c) (0xa0 <= (unsigned)(c) && (unsigned)(c) < 0xff) + + void + necmg_cons_update(int xsize, int ysize, + unsigned short *vvram, int start, int end) + { + int i, flag = 0; + int code, attr; + + if (start % xsize) { + for (i = (start / xsize) * xsize; i < start; i++) { + if (iskanji1(vvram[i])) { + flag = 1; + i++; + } else { + flag = 0; + } + } + } + if (flag) { + start -= 1; + } + + for (i = start; i <= end; i++) { + int x = i % xsize; + int y = i / xsize + 0; + if (ysize <= y) break; + if (iskanji1(vvram[i]&0xff) && x < xsize - 1) { + /* 2 byte code */ + attr = (vvram[i] >> 8) & 0xff; + code = (vvram[i++] & 0xff) << 8; + code |= (vvram[i] & 0xff); + } else { + code = vvram[i] & 0xff; + attr = (vvram[i] >> 8) & 0xff; + } + necmg_put_char(x, y, code, attr); + } + } + + void + necmg_cons_clear() + { + unsigned char *fb = NECMG_FRAMEBUFFER; + + int y; + for (y = 0; y < 240; y++) { + bzero(fb, 640/4); + fb += 0x100; + } + } + + #ifdef NECMG_ZOOMCONS + int + necmg_cons_get_zoompos() + { + return (mg_zoompos); + } + + int + necmg_cons_set_zoompos(int xsize, int ysize, unsigned short *vvram, int y) + { + int start, end; + int res = mg_zoompos; + + if (ysize <= y) { + y = ysize - 1; + } + if (mg_zoompos == y) { + return (mg_zoompos); + } + + if (mg_zoompos < 0) { + if (y < 0) { + /* nothing to do */ + return (res); + } else { + mg_zoompos = y; + start = y; + end = ysize - 1; + } + } else { + if (y < 0) { + start = mg_zoompos; + end = ysize - 1; + mg_zoompos = -1; + { /* clear bottom line */ + int i; + for (i = 0; i < xsize; i++) { + necmg_draw_char(i * 2, ysize * 9 + 8, ' ', 0, 9); + } + } + } else { + if (mg_zoompos < y) { + start = mg_zoompos; + end = y; + mg_zoompos = y; + } else { + start = y; + end = mg_zoompos; + mg_zoompos = y; + } + } + } + + necmg_cons_update(xsize, ysize, vvram, start * xsize, (end + 1) * xsize - 1); + + return (res); + } + #endif + + void + necmg_draw_char(int x, int y, int code, int attr, int size) + { + unsigned char *fb = NECMG_FRAMEBUFFER; + unsigned char *p, fore, back; + struct necmg_font_s f; + static data_table0[] = { + 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, + 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 + }; + static data_table1[] = { + 0x00, 0xc0, 0x30, 0xf0, 0x0c, 0xcc, 0x3c, 0xfc, + 0x03, 0xc3, 0x33, 0xf3, 0x0f, 0xcf, 0x3f, 0xff + }; + static color_table[] = { + /* 000 */ NECMG_WHITE, + /* 001 */ NECMG_LIGHTGRAY, + /* 010 */ NECMG_LIGHTGRAY, + /* 011 */ NECMG_DARKGRAY, + /* 100 */ NECMG_LIGHTGRAY, + /* 101 */ NECMG_DARKGRAY, + /* 110 */ NECMG_DARKGRAY, + /* 111 */ NECMG_BLACK + }; + + f = necmg_fonts[(attr & 0x08) ? 1 : 0]; /* 0x08 bit is Foreground Intensity*/ + fore = color_table[attr & 0x7]; + back = color_table[(attr >> 4) & 0x7]; + fb += x + y * 0x100; + + if (0x100 <= code) { + /* 16bit code */ + unsigned char *font_data = necmg_font_data(code); + if (size == 16) { + for (y = 0; y < 16; y++) { + unsigned char d; + d = data_table1[(*font_data>>4)&0x0f]; + *fb++ = (fore & d) | (back & ~d); + d = data_table1[*font_data&0x0f]; + *fb++ = (fore & d) | (back & ~d); + font_data++; + d = data_table1[(*font_data>>4)&0x0f]; + *fb++ = (fore & d) | (back & ~d); + d = data_table1[*font_data&0x0f]; + *fb++ = (fore & d) | (back & ~d); + font_data++; + fb += (0x100 - 4); + } + } else { + for (y = 0; y < 8; y++) { + unsigned char d, d0, d1; + d0 = data_table0[(*font_data>>4)&0x0f]; + d1 = data_table0[(*(font_data+2)>>4)&0x0f]; + d = ((d0 | d1) << 1) | (d0 & d1); + *fb++ = (fore & d) | (back & ~d); + d0 = data_table0[*font_data&0x0f]; + d1 = data_table0[*(font_data+2)&0x0f]; + d = ((d0 | d1) << 1) | (d0 & d1); + *fb++ = (fore & d) | (back & ~d); + font_data++; + + d0 = data_table0[(*font_data>>4)&0x0f]; + d1 = data_table0[(*(font_data+2)>>4)&0x0f]; + d = ((d0 | d1) << 1) | (d0 & d1); + *fb++ = (fore & d) | (back & ~d); + d0 = data_table0[*font_data&0x0f]; + d1 = data_table0[*(font_data+2)&0x0f]; + d = ((d0 | d1) << 1) | (d0 & d1); + *fb++ = (fore & d) | (back & ~d); + + font_data += 3; + fb += (0x100 - 4); + } + if (size == 9) { + bzero(fb, 4); + } + } + } else { + if (size == 16) { + unsigned char d; + p = necmg_font_data(code); + for (y = 0; y < 16; y++) { + d = data_table1[(*p>>4)&0x0f]; + *fb++ = (fore & d) | (back & ~d); + d = data_table1[(*p>>0)&0x0f]; + *fb++ = (fore & d) | (back & ~d); + p++; + fb += (0x100 - 2); + } + } else { + if (code < 0 || f.nchars <= code) { + code = 0; + } + p = f.data + f.width * f.height * code; + for (y = 0; y < f.height; y++) { + for (x = 0; x < f.width; x++) { + *fb++ = (fore & *p) | (back & ~*p); + p++; + } + fb += (0x100 - f.width); + } + if (size == 9) { + bzero(fb, f.width); + } + } + } + } + + #endif /* NECMG */ Index: PAO/sys/necmg/necmg/necmg_fonts.c diff -c /dev/null PAO/sys/necmg/necmg/necmg_fonts.c:1.1.4.1 *** /dev/null Fri Dec 25 10:51:46 1998 --- PAO/sys/necmg/necmg/necmg_fonts.c Sun Dec 6 07:49:21 1998 *************** *** 0 **** --- 1,363 ---- + /*- + * Copyright (c) 1998 Shin Takemura all rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: necmg_fonts.c,v 1.1.4.1 1998/12/05 22:49:21 itojun Exp $ + * + */ + #ifdef NECMG + #include + #include + #include + + #define D0 0x00 + #define D1 0xc0 + #define D2 0x30 + #define D3 0xf0 + #define D4 0x0c + #define D5 0xcc + #define D6 0x3c + #define D7 0xfc + #define D8 0x03 + #define D9 0xc3 + #define Da 0x33 + #define Db 0xf3 + #define Dc 0x0f + #define Dd 0xcf + #define De 0x3f + #define Df 0xff + + static unsigned char font_clB8x8_data[] = { + /* + COMMENT $XConsortium: clB8x8.bdf,v 1.2 94/04/11 12:07:01 gildea Exp $ + COMMENT + COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org + COMMENT 399 Beacon Ave. + COMMENT St. Paul, MN 55104-3527 + COMMENT + COMMENT Permission to use, copy, modify, and distribute this software and + COMMENT its documentation for any purpose and without fee is hereby + COMMENT granted, provided that the above copyright notice appear in all + COMMENT copies and that both that copyright notice and this permission + COMMENT notice appear in supporting documentation, and that the name of + COMMENT Dale Schumacher not be used in advertising or publicity pertaining to + COMMENT distribution of the software without specific, written prior + COMMENT permission. Dale Schumacher makes no representations about the + COMMENT suitability of this software for any purpose. It is provided "as + COMMENT is" without express or implied warranty. + */ + /* code 00 */ Df,Df,Dd,Db,D0,D0,D0,D0,D0,D0,D8,D1,Dc,D3,Df,Df, + /* code 01 */ D0,D8,D1,D4,D2,D2,D7,D7,D1,D4,D1,D4,D1,D4,D1,Dc, + /* code 02 */ D1,Dc,D1,D4,D1,D4,D1,D4,D7,D7,D2,D2,D1,D4,D0,D8, + /* code 03 */ D0,D8,D0,Dc,D7,Da,D4,D1,D7,Da,D0,Dc,D0,D8,D0,D0, + /* code 04 */ D0,D8,D1,D8,D2,Df,D4,D1,D2,Df,D1,D8,D0,D8,D0,D0, + /* code 05 */ D3,De,D5,Dd,D6,Db,D7,D7,D6,Db,D5,Dd,D3,De,D0,D0, + /* code 06 */ D7,Df,D7,Df,D7,Df,D7,De,D7,Dd,D7,Db,D7,D7,D0,D0, + /* code 07 */ D7,D7,D6,Db,D5,Dd,D3,De,D5,Dd,D6,Db,D7,D7,D0,D0, + /* code 08 */ D6,D0,D5,D0,D6,D0,D5,D3,D6,D4,D0,D2,D0,D1,D0,D6, + /* code 09 */ D5,D0,D5,D0,D7,D0,D5,D7,D5,D2,D0,D2,D0,D2,D0,D2, + /* code 0a */ D4,D0,D4,D0,D4,D0,D4,D7,D7,D4,D0,D6,D0,D4,D0,D4, + /* code 0b */ D5,D0,D5,D0,D5,D0,D2,D7,D2,D2,D0,D2,D0,D2,D0,D2, + /* code 0c */ D7,D0,D4,D0,D6,D0,D4,D7,D4,D4,D0,D6,D0,D4,D0,D4, + /* code 0d */ D3,D0,D4,D0,D4,D0,D4,D6,D3,D5,D0,D6,D0,D5,D0,D5, + /* code 0e */ D0,D5,D0,D5,D0,D5,D0,Dd,D0,Dd,D1,D9,D7,D9,D7,D1, + /* code 0f */ Da,D0,Da,D0,Da,D0,Db,D0,Db,D0,D9,D8,D9,De,D8,De, + /* code 10 */ D1,D8,D6,D6,D6,D6,D0,D0,D6,D6,D6,D6,D1,D8,D0,D0, + /* code 11 */ D0,D0,D0,D6,D0,D6,D0,D0,D0,D6,D0,D6,D0,D0,D0,D0, + /* code 12 */ D1,D8,D0,D6,D0,D6,D1,D8,D6,D0,D6,D0,D1,D8,D0,D0, + /* code 13 */ D1,D8,D0,D6,D0,D6,D1,D8,D0,D6,D0,D6,D1,D8,D0,D0, + /* code 14 */ D0,D0,D6,D6,D6,D6,D1,D8,D0,D6,D0,D6,D0,D0,D0,D0, + /* code 15 */ D1,D8,D6,D0,D6,D0,D1,D8,D0,D6,D0,D6,D1,D8,D0,D0, + /* code 16 */ D1,D8,D6,D0,D6,D0,D1,D8,D6,D6,D6,D6,D1,D8,D0,D0, + /* code 17 */ D1,D8,D0,D6,D0,D6,D0,D0,D0,D6,D0,D6,D0,D0,D0,D0, + /* code 18 */ D1,D8,D6,D6,D6,D6,D1,D8,D6,D6,D6,D6,D1,D8,D0,D0, + /* code 19 */ D1,D8,D6,D6,D6,D6,D1,D8,D0,D6,D0,D6,D1,D8,D0,D0, + /* code 1a */ D0,D0,D0,D0,D3,De,D0,D3,D7,Df,D6,D3,D3,De,D0,D0, + /* code 1b */ D7,D0,D4,D0,D7,D0,D4,D3,D7,D4,D0,D4,D0,D4,D0,D3, + /* code 1c */ D0,D7,D0,Df,D1,Df,D1,D8,D1,D8,D1,D0,D1,De,D1,D7, + /* code 1d */ Df,D0,Df,D8,De,Dc,D0,D4,D0,D4,D0,D4,D3,Dc,D5,D4, + /* code 1e */ D1,D1,D0,Db,D0,Dd,D0,D6,D0,D7,D2,De,D3,D9,D3,D8, + /* code 1f */ D0,D4,D2,D8,Dd,D8,D2,D8,Dd,D0,D1,D0,De,D0,D0,D0, + /* code 20 */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 21 */ D1,D8,D1,D8,D1,D8,D1,D8,D1,D8,D1,D8,D0,D0,D1,D8, + /* code 22 */ D1,D4,D1,D4,D1,D4,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 23 */ D0,D0,D2,D4,D7,De,D2,D4,D2,D4,D7,De,D2,D4,D0,D0, + /* code 24 */ D0,D8,D1,De,D2,D8,D1,Dc,D0,Da,D3,Dc,D0,D8,D0,D0, + /* code 25 */ D2,D0,D5,D2,D2,D4,D0,D8,D1,D2,D2,D5,D0,D2,D0,D0, + /* code 26 */ D3,D8,D4,D0,D2,D0,D3,D0,D4,Da,D4,D4,D3,Da,D0,D0, + /* code 27 */ D0,Dc,D0,D8,D1,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 28 */ D0,Dc,D1,D8,D3,D0,D3,D0,D3,D0,D1,D8,D0,Dc,D0,D0, + /* code 29 */ D1,D8,D0,Dc,D0,D6,D0,D6,D0,D6,D0,Dc,D1,D8,D0,D0, + /* code 2a */ D0,D8,D0,D8,D6,Db,D1,Dc,D0,D8,D1,D4,D2,D2,D0,D0, + /* code 2b */ D0,D8,D0,D8,D0,D8,D7,Df,D0,D8,D0,D8,D0,D8,D0,D0, + /* code 2c */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D1,D8,D1,D0,D2,D0, + /* code 2d */ D0,D0,D0,D0,D0,D0,D7,Df,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 2e */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D1,D8,D1,D8,D0,D0, + /* code 2f */ D0,D4,D0,D4,D0,D8,D0,D8,D1,D0,D1,D0,D2,D0,D2,D0, + /* code 30 */ D3,Dc,D6,D6,D6,D6,D6,D6,D6,D6,D6,D6,D3,Dc,D0,D0, + /* code 31 */ D0,Dc,D1,Dc,D0,Dc,D0,Dc,D0,Dc,D0,Dc,D0,Dc,D0,D0, + /* code 32 */ D3,Dc,D6,D6,D0,D6,D0,Dc,D1,D8,D3,D0,D7,De,D0,D0, + /* code 33 */ D3,Dc,D6,D6,D0,D6,D1,Dc,D0,D6,D6,D6,D3,Dc,D0,D0, + /* code 34 */ D0,Dc,D1,Dc,D3,Dc,D6,Dc,D7,De,D0,Dc,D1,De,D0,D0, + /* code 35 */ D7,De,D6,D0,D7,Dc,D0,D6,D0,D6,D6,D6,D3,Dc,D0,D0, + /* code 36 */ D1,Dc,D3,D0,D6,D0,D7,Dc,D6,D6,D6,D6,D3,Dc,D0,D0, + /* code 37 */ D7,De,D6,D6,D0,D6,D0,Dc,D0,Dc,D1,D8,D1,D8,D0,D0, + /* code 38 */ D3,Dc,D6,D6,D6,D6,D3,Dc,D6,D6,D6,D6,D3,Dc,D0,D0, + /* code 39 */ D3,Dc,D6,D6,D6,D6,D3,De,D0,D6,D0,Dc,D3,D8,D0,D0, + /* code 3a */ D0,D0,D1,D8,D1,D8,D0,D0,D0,D0,D1,D8,D1,D8,D0,D0, + /* code 3b */ D0,D0,D1,D8,D1,D8,D0,D0,D0,D0,D1,D8,D1,D0,D2,D0, + /* code 3c */ D0,D0,D0,D7,D1,Dc,D7,D0,D1,Dc,D0,D7,D0,D0,D0,D0, + /* code 3d */ D0,D0,D0,D0,D7,Df,D0,D0,D0,D0,D7,Df,D0,D0,D0,D0, + /* code 3e */ D0,D0,D7,D0,D1,Dc,D0,D7,D1,Dc,D7,D0,D0,D0,D0,D0, + /* code 3f */ D3,Dc,D6,D6,D0,D6,D0,Dc,D1,D8,D0,D0,D1,D8,D0,D0, + /* code 40 */ D3,De,D4,D1,D5,Dd,D5,D5,D5,De,D4,D0,D3,De,D0,D0, + /* code 41 */ D1,D8,D1,D8,D3,Dc,D3,D4,D7,De,D6,D2,De,D3,D0,D0, + /* code 42 */ D7,De,D6,D3,D6,D3,D7,De,D6,D3,D6,D3,D7,De,D0,D0, + /* code 43 */ D1,De,D3,D3,D6,D0,D6,D0,D6,D0,D3,D3,D1,De,D0,D0, + /* code 44 */ D7,Dc,D6,D6,D6,D3,D6,D3,D6,D3,D6,D6,D7,Dc,D0,D0, + /* code 45 */ D7,Df,D6,D0,D6,D0,D7,Dc,D6,D0,D6,D0,D7,Df,D0,D0, + /* code 46 */ D7,Df,D6,D0,D6,D0,D7,Dc,D6,D0,D6,D0,D6,D0,D0,D0, + /* code 47 */ D1,De,D3,D3,D6,D0,D6,D0,D6,D7,D3,D3,D1,Df,D0,D0, + /* code 48 */ D6,D3,D6,D3,D6,D3,D7,Df,D6,D3,D6,D3,D6,D3,D0,D0, + /* code 49 */ D7,De,D1,D8,D1,D8,D1,D8,D1,D8,D1,D8,D7,De,D0,D0, + /* code 4a */ D1,De,D0,D6,D0,D6,D0,D6,D6,D6,D6,D6,D3,Dc,D0,D0, + /* code 4b */ D6,D3,D6,D6,D6,Dc,D7,D8,D6,Dc,D6,D6,D6,D3,D0,D0, + /* code 4c */ D6,D0,D6,D0,D6,D0,D6,D0,D6,D0,D6,D0,D7,De,D0,D0, + /* code 4d */ D6,D3,D6,D3,D7,D7,D6,Db,D6,Db,D6,D3,D6,D3,D0,D0, + /* code 4e */ D6,D3,D7,D3,D7,D3,D6,Db,D6,Db,D6,D7,D6,D3,D0,D0, + /* code 4f */ D1,Dc,D3,D6,D6,D3,D6,D3,D6,D3,D3,D6,D1,Dc,D0,D0, + /* code 50 */ D7,De,D6,D3,D6,D3,D7,De,D6,D0,D6,D0,D6,D0,D0,D0, + /* code 51 */ D1,Dc,D3,D6,D6,D3,D6,D3,D6,D3,D3,D6,D1,Dc,D0,D6, + /* code 52 */ D7,De,D6,D3,D6,D3,D7,De,D6,Dc,D6,D6,D6,D3,D0,D0, + /* code 53 */ D3,De,D6,D3,D6,D0,D3,De,D0,D3,D6,D3,D3,De,D0,D0, + /* code 54 */ D7,De,D1,D8,D1,D8,D1,D8,D1,D8,D1,D8,D1,D8,D0,D0, + /* code 55 */ D6,D3,D6,D3,D6,D3,D6,D3,D6,D3,D6,D3,D3,De,D0,D0, + /* code 56 */ D6,D3,D6,D3,D6,D3,D3,D6,D3,D6,D1,Dc,D1,Dc,D0,D0, + /* code 57 */ D6,D3,D6,D3,D6,Db,D6,Db,D6,Db,D7,D7,D6,D3,D0,D0, + /* code 58 */ D6,D6,D6,D6,D3,Dc,D1,D8,D3,Dc,D6,D6,D6,D6,D0,D0, + /* code 59 */ D6,D6,D6,D6,D3,Dc,D1,D8,D1,D8,D1,D8,D1,D8,D0,D0, + /* code 5a */ D7,De,D0,D6,D0,Dc,D1,D8,D3,D0,D6,D0,D7,De,D0,D0, + /* code 5b */ D1,De,D1,D8,D1,D8,D1,D8,D1,D8,D1,D8,D1,De,D0,D0, + /* code 5c */ D2,D0,D2,D0,D1,D0,D1,D0,D0,D8,D0,D8,D0,D4,D0,D4, + /* code 5d */ D3,Dc,D0,Dc,D0,Dc,D0,Dc,D0,Dc,D0,Dc,D3,Dc,D0,D0, + /* code 5e */ D1,D8,D3,D4,D6,D2,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 5f */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D7,Df,D0,D0, + /* code 60 */ D1,D8,D0,D8,D0,D4,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 61 */ D0,D0,D0,D0,D3,Df,D6,D3,D6,D3,D6,D7,D3,Db,D0,D0, + /* code 62 */ D6,D0,D6,D0,D7,De,D6,D3,D6,D3,D6,D3,D7,De,D0,D0, + /* code 63 */ D0,D0,D0,D0,D3,De,D6,D0,D6,D0,D6,D0,D3,De,D0,D0, + /* code 64 */ D0,D3,D0,D3,D3,Df,D6,D3,D6,D3,D6,D3,D3,Df,D0,D0, + /* code 65 */ D0,D0,D0,D0,D3,De,D6,D3,D7,Df,D6,D0,D3,De,D0,D0, + /* code 66 */ D1,De,D3,D0,D7,Dc,D3,D0,D3,D0,D3,D0,D3,D0,D0,D0, + /* code 67 */ D0,D0,D0,D0,D3,Df,D6,D3,D6,D3,D3,Df,D0,D3,D3,De, + /* code 68 */ D6,D0,D6,D0,D7,De,D6,D3,D6,D3,D6,D3,D6,D3,D0,D0, + /* code 69 */ D1,D8,D0,D0,D7,D8,D1,D8,D1,D8,D1,D8,D7,De,D0,D0, + /* code 6a */ D0,D6,D0,D0,D1,De,D0,D6,D0,D6,D0,D6,D0,D6,D3,Dc, + /* code 6b */ D6,D0,D6,D0,D6,D6,D6,Dc,D7,D8,D6,Dc,D6,D6,D0,D0, + /* code 6c */ D3,D8,D1,D8,D1,D8,D1,D8,D1,D8,D1,D8,D3,Dc,D0,D0, + /* code 6d */ D0,D0,D0,D0,D7,D6,D6,Db,D6,Db,D6,Db,D6,D3,D0,D0, + /* code 6e */ D0,D0,D0,D0,D6,De,D7,D3,D6,D3,D6,D3,D6,D3,D0,D0, + /* code 6f */ D0,D0,D0,D0,D3,De,D6,D3,D6,D3,D6,D3,D3,De,D0,D0, + /* code 70 */ D0,D0,D0,D0,D7,De,D6,D3,D6,D3,D6,D3,D7,De,D6,D0, + /* code 71 */ D0,D0,D0,D0,D3,Df,D6,D3,D6,D3,D6,D3,D3,Df,D0,D3, + /* code 72 */ D0,D0,D0,D0,D6,De,D7,D0,D6,D0,D6,D0,D6,D0,D0,D0, + /* code 73 */ D0,D0,D0,D0,D3,De,D6,D0,D3,Dc,D0,D6,D7,Dc,D0,D0, + /* code 74 */ D1,D8,D1,D8,D7,De,D1,D8,D1,D8,D1,D8,D0,De,D0,D0, + /* code 75 */ D0,D0,D0,D0,D6,D3,D6,D3,D6,D3,D6,D7,D3,Db,D0,D0, + /* code 76 */ D0,D0,D0,D0,D7,D7,D3,D6,D3,D6,D1,Dc,D1,Dc,D0,D0, + /* code 77 */ D0,D0,D0,D0,D6,D3,D6,Db,D6,Db,D6,Db,D3,D6,D0,D0, + /* code 78 */ D0,D0,D0,D0,D6,D6,D3,Dc,D1,D8,D3,Dc,D6,D6,D0,D0, + /* code 79 */ D0,D0,D0,D0,D6,D6,D6,D6,D6,D6,D3,De,D0,D6,D3,Dc, + /* code 7a */ D0,D0,D0,D0,D7,De,D0,Dc,D1,D8,D3,D0,D7,De,D0,D0, + /* code 7b */ D0,De,D1,D8,D1,D8,D3,D0,D1,D8,D1,D8,D0,De,D0,D0, + /* code 7c */ D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D0, + /* code 7d */ D3,D8,D0,Dc,D0,Dc,D0,D6,D0,Dc,D0,Dc,D3,D8,D0,D0, + /* code 7e */ D3,D1,D4,D9,D4,D6,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 7f */ D0,D0,D1,D8,D1,D8,D3,D4,D3,D4,D6,D2,D7,De,D0,D0, + }; + static unsigned char font_clR8x8_data[] = { + /* + COMMENT $XConsortium: clR8x8.bdf,v 1.2 94/04/11 12:08:54 gildea Exp $ + COMMENT + COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org + COMMENT 399 Beacon Ave. + COMMENT St. Paul, MN 55104-3527 + COMMENT + COMMENT Permission to use, copy, modify, and distribute this software and + COMMENT its documentation for any purpose and without fee is hereby + COMMENT granted, provided that the above copyright notice appear in all + COMMENT copies and that both that copyright notice and this permission + COMMENT notice appear in supporting documentation, and that the name of + COMMENT Dale Schumacher not be used in advertising or publicity pertaining to + COMMENT distribution of the software without specific, written prior + COMMENT permission. Dale Schumacher makes no representations about the + COMMENT suitability of this software for any purpose. It is provided "as + COMMENT is" without express or implied warranty. + */ + /* code 00 */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 01 */ D0,D8,D1,D4,D2,D2,D7,D7,D1,D4,D1,D4,D1,D4,D1,Dc, + /* code 02 */ D1,Dc,D1,D4,D1,D4,D1,D4,D7,D7,D2,D2,D1,D4,D0,D8, + /* code 03 */ D0,D8,D0,Dc,D7,Da,D4,D1,D7,Da,D0,Dc,D0,D8,D0,D0, + /* code 04 */ D0,D8,D1,D8,D2,Df,D4,D1,D2,Df,D1,D8,D0,D8,D0,D0, + /* code 05 */ D3,De,D5,Dd,D6,Db,D7,D7,D6,Db,D5,Dd,D3,De,D0,D0, + /* code 06 */ D7,Df,D7,Df,D7,Df,D7,De,D7,Dd,D7,Db,D7,D7,D0,D0, + /* code 07 */ D7,D7,D6,Db,D5,Dd,D3,De,D5,Dd,D6,Db,D7,D7,D0,D0, + /* code 08 */ D6,D0,D5,D0,D6,D0,D5,D3,D6,D4,D0,D2,D0,D1,D0,D6, + /* code 09 */ D5,D0,D5,D0,D7,D0,D5,D7,D5,D2,D0,D2,D0,D2,D0,D2, + /* code 0a */ D4,D0,D4,D0,D4,D0,D4,D7,D7,D4,D0,D6,D0,D4,D0,D4, + /* code 0b */ D5,D0,D5,D0,D5,D0,D2,D7,D2,D2,D0,D2,D0,D2,D0,D2, + /* code 0c */ D7,D0,D4,D0,D6,D0,D4,D7,D4,D4,D0,D6,D0,D4,D0,D4, + /* code 0d */ D3,D0,D4,D0,D4,D0,D4,D6,D3,D5,D0,D6,D0,D5,D0,D5, + /* code 0e */ D0,D5,D0,D5,D0,D5,D0,Dd,D0,Dd,D0,Dd,D1,D9,D7,D9, + /* code 0f */ Da,D0,Da,D0,Da,D0,Db,D0,Db,D0,Db,D0,D9,D8,D9,De, + /* code 10 */ D1,D8,D4,D2,D4,D2,D0,D0,D4,D2,D4,D2,D1,D8,D0,D0, + /* code 11 */ D0,D0,D0,D2,D0,D2,D0,D0,D0,D2,D0,D2,D0,D0,D0,D0, + /* code 12 */ D1,D8,D0,D2,D0,D2,D1,D8,D4,D0,D4,D0,D1,D8,D0,D0, + /* code 13 */ D1,D8,D0,D2,D0,D2,D1,D8,D0,D2,D0,D2,D1,D8,D0,D0, + /* code 14 */ D0,D0,D4,D2,D4,D2,D1,D8,D0,D2,D0,D2,D0,D0,D0,D0, + /* code 15 */ D1,D8,D4,D0,D4,D0,D1,D8,D0,D2,D0,D2,D1,D8,D0,D0, + /* code 16 */ D1,D8,D4,D0,D4,D0,D1,D8,D4,D2,D4,D2,D1,D8,D0,D0, + /* code 17 */ D1,D8,D0,D2,D0,D2,D0,D0,D0,D2,D0,D2,D0,D0,D0,D0, + /* code 18 */ D1,D8,D4,D2,D4,D2,D1,D8,D4,D2,D4,D2,D1,D8,D0,D0, + /* code 19 */ D1,D8,D4,D2,D4,D2,D1,D8,D0,D2,D0,D2,D1,D8,D0,D0, + /* code 1a */ D0,D0,D0,D0,D3,De,D0,D1,D7,Df,D4,D1,D3,De,D0,D0, + /* code 1b */ D7,D0,D4,D0,D7,D0,D4,D3,D7,D4,D0,D4,D0,D4,D0,D3, + /* code 1c */ D0,D7,D0,Df,D1,Df,D1,D8,D1,D8,D1,D0,D1,De,D1,D7, + /* code 1d */ Df,D0,Df,D8,De,Dc,D0,D4,D0,D4,D0,D4,D3,Dc,D5,D4, + /* code 1e */ D1,D1,D0,Db,D0,Dd,D0,D6,D0,D7,D2,De,D3,D9,D3,D8, + /* code 1f */ D0,D4,D2,D8,Dd,D8,D2,D8,Dd,D0,D1,D0,De,D0,D0,D0, + /* code 20 */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 21 */ D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D0,D0,D8,D0,D0, + /* code 22 */ D1,D4,D1,D4,D1,D4,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 23 */ D1,D4,D1,D4,D3,De,D1,D4,D3,De,D1,D4,D1,D4,D0,D0, + /* code 24 */ D0,D8,D1,De,D2,D8,D1,Dc,D0,Da,D3,Dc,D0,D8,D0,D0, + /* code 25 */ D2,D2,D5,D4,D2,D4,D0,D8,D1,D2,D1,D5,D2,D2,D0,D0, + /* code 26 */ D3,D8,D4,D0,D2,D0,D3,D0,D4,Da,D4,D4,D3,Da,D0,D0, + /* code 27 */ D0,Dc,D0,D8,D1,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 28 */ D0,D4,D0,D8,D1,D0,D1,D0,D1,D0,D0,D8,D0,D4,D0,D0, + /* code 29 */ D1,D0,D0,D8,D0,D4,D0,D4,D0,D4,D0,D8,D1,D0,D0,D0, + /* code 2a */ D0,D8,D0,D8,D6,Db,D1,Dc,D0,D8,D1,D4,D2,D2,D0,D0, + /* code 2b */ D0,D8,D0,D8,D0,D8,D7,Df,D0,D8,D0,D8,D0,D8,D0,D0, + /* code 2c */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D1,D8,D1,D0,D2,D0, + /* code 2d */ D0,D0,D0,D0,D0,D0,D7,Df,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 2e */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D1,D8,D1,D8,D0,D0, + /* code 2f */ D0,D4,D0,D4,D0,D8,D0,D8,D1,D0,D1,D0,D2,D0,D2,D0, + /* code 30 */ D3,Dc,D4,D2,D4,D2,D4,D2,D4,D2,D4,D2,D3,Dc,D0,D0, + /* code 31 */ D0,D8,D1,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D0, + /* code 32 */ D3,Dc,D4,D2,D0,D4,D0,D8,D1,D0,D2,D0,D7,De,D0,D0, + /* code 33 */ D3,Dc,D4,D2,D0,D2,D1,Dc,D0,D2,D4,D2,D3,Dc,D0,D0, + /* code 34 */ D0,D4,D0,Dc,D1,D4,D2,D4,D7,De,D0,D4,D0,De,D0,D0, + /* code 35 */ D7,De,D4,D0,D4,D0,D7,Dc,D0,D2,D0,D2,D7,Dc,D0,D0, + /* code 36 */ D1,Dc,D2,D0,D4,D0,D7,Dc,D4,D2,D4,D2,D3,Dc,D0,D0, + /* code 37 */ D7,De,D0,D2,D0,D4,D0,D4,D0,D8,D0,D8,D1,D0,D0,D0, + /* code 38 */ D3,Dc,D4,D2,D4,D2,D3,Dc,D4,D2,D4,D2,D3,Dc,D0,D0, + /* code 39 */ D3,Dc,D4,D2,D4,D2,D3,De,D0,D2,D0,D4,D3,D8,D0,D0, + /* code 3a */ D0,D0,D1,D8,D1,D8,D0,D0,D0,D0,D1,D8,D1,D8,D0,D0, + /* code 3b */ D0,D0,D1,D8,D1,D8,D0,D0,D0,D0,D1,D8,D1,D0,D2,D0, + /* code 3c */ D0,D0,D0,D6,D1,D8,D6,D0,D1,D8,D0,D6,D0,D0,D0,D0, + /* code 3d */ D0,D0,D0,D0,D7,Df,D0,D0,D0,D0,D7,Df,D0,D0,D0,D0, + /* code 3e */ D0,D0,D6,D0,D1,D8,D0,D6,D1,D8,D6,D0,D0,D0,D0,D0, + /* code 3f */ D1,Dc,D2,D2,D0,D2,D0,D4,D0,D8,D0,D0,D0,D8,D0,D0, + /* code 40 */ D1,Dc,D2,D2,D4,D9,D5,D5,D4,Da,D2,D0,D1,Dc,D0,D0, + /* code 41 */ D0,D8,D0,D8,D1,Dc,D1,D4,D3,De,D2,D2,D6,D3,D0,D0, + /* code 42 */ D7,De,D4,D1,D4,D1,D7,De,D4,D1,D4,D1,D7,De,D0,D0, + /* code 43 */ D1,De,D2,D1,D4,D0,D4,D0,D4,D0,D2,D1,D1,De,D0,D0, + /* code 44 */ D7,Dc,D4,D2,D4,D1,D4,D1,D4,D1,D4,D2,D7,Dc,D0,D0, + /* code 45 */ D7,Df,D4,D0,D4,D0,D7,Dc,D4,D0,D4,D0,D7,Df,D0,D0, + /* code 46 */ D7,Df,D4,D0,D4,D0,D7,Dc,D4,D0,D4,D0,D4,D0,D0,D0, + /* code 47 */ D1,De,D2,D1,D4,D0,D4,D7,D4,D1,D2,D1,D1,Df,D0,D0, + /* code 48 */ D4,D1,D4,D1,D4,D1,D7,Df,D4,D1,D4,D1,D4,D1,D0,D0, + /* code 49 */ D3,De,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D3,De,D0,D0, + /* code 4a */ D0,De,D0,D2,D0,D2,D0,D2,D4,D2,D4,D2,D3,Dc,D0,D0, + /* code 4b */ D4,D2,D4,D4,D4,D8,D7,D0,D4,D8,D4,D4,D4,D2,D0,D0, + /* code 4c */ D4,D0,D4,D0,D4,D0,D4,D0,D4,D0,D4,D0,D7,De,D0,D0, + /* code 4d */ D4,D1,D6,D3,D5,D5,D4,D9,D4,D1,D4,D1,D4,D1,D0,D0, + /* code 4e */ D4,D1,D6,D1,D5,D1,D4,D9,D4,D5,D4,D3,D4,D1,D0,D0, + /* code 4f */ D1,Dc,D2,D2,D4,D1,D4,D1,D4,D1,D2,D2,D1,Dc,D0,D0, + /* code 50 */ D7,De,D4,D1,D4,D1,D7,De,D4,D0,D4,D0,D4,D0,D0,D0, + /* code 51 */ D1,Dc,D2,D2,D4,D1,D4,D1,D4,D1,D2,D2,D1,Dc,D0,D7, + /* code 52 */ D7,De,D4,D1,D4,D1,D7,De,D4,D4,D4,D2,D4,D1,D0,D0, + /* code 53 */ D3,De,D4,D1,D4,D0,D3,De,D0,D1,D4,D1,D3,De,D0,D0, + /* code 54 */ D7,Df,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D0, + /* code 55 */ D4,D1,D4,D1,D4,D1,D4,D1,D4,D1,D4,D1,D3,De,D0,D0, + /* code 56 */ D6,D3,D2,D2,D2,D2,D1,D4,D1,D4,D0,D8,D0,D8,D0,D0, + /* code 57 */ D4,D1,D4,D1,D4,D1,D4,D9,D5,D5,D6,D3,D4,D1,D0,D0, + /* code 58 */ D4,D1,D2,D2,D1,D4,D0,D8,D1,D4,D2,D2,D4,D1,D0,D0, + /* code 59 */ D4,D1,D2,D2,D1,D4,D0,D8,D0,D8,D0,D8,D0,D8,D0,D0, + /* code 5a */ D7,Df,D0,D2,D0,D4,D0,D8,D1,D0,D2,D0,D7,Df,D0,D0, + /* code 5b */ D0,De,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,De,D0,D0, + /* code 5c */ D2,D0,D2,D0,D1,D0,D1,D0,D0,D8,D0,D8,D0,D4,D0,D4, + /* code 5d */ D3,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D3,D8,D0,D0, + /* code 5e */ D0,D8,D1,D4,D2,D2,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 5f */ D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0,D7,Df, + /* code 60 */ D1,D8,D0,D8,D0,D4,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 61 */ D0,D0,D0,D0,D3,Df,D4,D1,D4,D1,D4,D3,D3,Dd,D0,D0, + /* code 62 */ D4,D0,D4,D0,D7,De,D4,D1,D4,D1,D4,D1,D7,De,D0,D0, + /* code 63 */ D0,D0,D0,D0,D3,De,D4,D0,D4,D0,D4,D0,D3,De,D0,D0, + /* code 64 */ D0,D1,D0,D1,D3,Df,D4,D1,D4,D1,D4,D1,D3,Df,D0,D0, + /* code 65 */ D0,D0,D0,D0,D3,De,D4,D1,D7,Df,D4,D0,D3,De,D0,D0, + /* code 66 */ D1,De,D2,D0,D7,D8,D2,D0,D2,D0,D2,D0,D2,D0,D0,D0, + /* code 67 */ D0,D0,D0,D0,D3,Df,D4,D1,D4,D1,D3,Df,D0,D1,D3,De, + /* code 68 */ D4,D0,D4,D0,D7,De,D4,D1,D4,D1,D4,D1,D4,D1,D0,D0, + /* code 69 */ D0,D8,D0,D0,D3,D8,D0,D8,D0,D8,D0,D8,D3,De,D0,D0, + /* code 6a */ D0,D2,D0,D0,D1,De,D0,D2,D0,D2,D0,D2,D0,D2,D3,Dc, + /* code 6b */ D4,D0,D4,D0,D4,D6,D4,D8,D7,D0,D4,D8,D4,D6,D0,D0, + /* code 6c */ D1,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D1,Dc,D0,D0, + /* code 6d */ D0,D0,D0,D0,D7,D6,D4,D9,D4,D9,D4,D9,D4,D1,D0,D0, + /* code 6e */ D0,D0,D0,D0,D5,De,D6,D1,D4,D1,D4,D1,D4,D1,D0,D0, + /* code 6f */ D0,D0,D0,D0,D3,De,D4,D1,D4,D1,D4,D1,D3,De,D0,D0, + /* code 70 */ D0,D0,D0,D0,D7,De,D4,D1,D4,D1,D4,D1,D7,De,D4,D0, + /* code 71 */ D0,D0,D0,D0,D3,Df,D4,D1,D4,D1,D4,D1,D3,Df,D0,D1, + /* code 72 */ D0,D0,D0,D0,D2,De,D3,D0,D2,D0,D2,D0,D2,D0,D0,D0, + /* code 73 */ D0,D0,D0,D0,D3,De,D4,D0,D3,Dc,D0,D2,D7,Dc,D0,D0, + /* code 74 */ D1,D0,D1,D0,D7,De,D1,D0,D1,D0,D1,D0,D0,De,D0,D0, + /* code 75 */ D0,D0,D0,D0,D4,D1,D4,D1,D4,D1,D4,D3,D3,Dd,D0,D0, + /* code 76 */ D0,D0,D0,D0,D6,D3,D2,D2,D1,D4,D1,D4,D0,D8,D0,D0, + /* code 77 */ D0,D0,D0,D0,D4,D1,D4,D9,D4,D9,D4,D9,D3,D6,D0,D0, + /* code 78 */ D0,D0,D0,D0,D6,D3,D1,D4,D0,D8,D1,D4,D6,D3,D0,D0, + /* code 79 */ D0,D0,D0,D0,D4,D2,D4,D2,D4,D2,D3,De,D0,D2,D3,Dc, + /* code 7a */ D0,D0,D0,D0,D7,De,D0,D4,D1,D8,D2,D0,D7,De,D0,D0, + /* code 7b */ D0,D4,D0,D8,D0,D8,D1,D0,D0,D8,D0,D8,D0,D4,D0,D0, + /* code 7c */ D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D8,D0,D0, + /* code 7d */ D1,D0,D0,D8,D0,D8,D0,D4,D0,D8,D0,D8,D1,D0,D0,D0, + /* code 7e */ D3,D1,D4,D9,D4,D6,D0,D0,D0,D0,D0,D0,D0,D0,D0,D0, + /* code 7f */ D0,D0,D0,D8,D0,D8,D1,D4,D1,D4,D2,D2,D3,De,D0,D0, + }; + #define font_clB8x8_nchars 128 + #define font_clB8x8_width 8 + #define font_clB8x8_height 8 + #define font_clR8x8_nchars 128 + #define font_clR8x8_width 8 + #define font_clR8x8_height 8 + + struct necmg_font_s necmg_fonts[] = { + { font_clR8x8_data, ((font_clR8x8_width + 7)/8)*2, + font_clR8x8_height, font_clR8x8_nchars }, + { font_clB8x8_data, ((font_clB8x8_width + 7)/8)*2, + font_clB8x8_height, font_clB8x8_nchars }, + }; + + #endif /* NECMG */ Index: PAO/sys/necmg/necmg/necmg_icon.c diff -c /dev/null PAO/sys/necmg/necmg/necmg_icon.c:1.1.4.1 *** /dev/null Fri Dec 25 10:51:46 1998 --- PAO/sys/necmg/necmg/necmg_icon.c Sun Dec 6 07:49:22 1998 *************** *** 0 **** --- 1,199 ---- + /*- + * Copyright (c) 1998 Shin Takemura all rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: necmg_icon.c,v 1.1.4.1 1998/12/05 22:49:22 itojun Exp $ + * + */ + #ifdef NECMG + #include + + #include + #include + + #define D0 0x00 + #define D1 0xc0 + #define D2 0x30 + #define D3 0xf0 + #define D4 0x0c + #define D5 0xcc + #define D6 0x3c + #define D7 0xfc + #define D8 0x03 + #define D9 0xc3 + #define Da 0x33 + #define Db 0xf3 + #define Dc 0x0f + #define Dd 0xcf + #define De 0x3f + #define Df 0xff + + unsigned char necmg_icon8x8[][16] = { + { + D0, D0, /*........*/ + D0, D0, /*........*/ + D0, D0, /*........*/ + D0, D0, /*........*/ + D0, D0, /*........*/ + D0, D0, /*........*/ + D0, D0, /*........*/ + D0, D0, /*........*/ + }, + { + D0, D0, /*........*/ + D1, D8, /*...##...*/ + D3, D8, /*..###...*/ + D1, D8, /*...##...*/ + D1, D8, /*...##...*/ + D1, D8, /*...##...*/ + D1, D8, /*...##...*/ + D0, D0, /*........*/ + }, + { + D0, D0, /*........*/ + D1, D8, /*...##...*/ + D1, D8, /*...##...*/ + D3, D4, /*..##.#..*/ + D7, De, /*.######.*/ + D6, D2, /*.##...#.*/ + D6, D2, /*.##...#.*/ + D0, D0, /*........*/ + }, + { + D0, D0, /*........*/ + D7, De, /*.######.*/ + D0, D2, /*......#.*/ + D1, D4, /*...#.#..*/ + D1, D8, /*...##...*/ + D2, D0, /*..#.....*/ + D4, D0, /*.#......*/ + D0, D0, /*........*/ + }, + { + D0, D0, /*........*/ + D7, De, /*.######.*/ + D0, Dc, /*....##..*/ + D1, D8, /*...##...*/ + D1, D8, /*...##...*/ + D3, D0, /*..##....*/ + D7, De, /*.######.*/ + D0, D0, /*........*/ + }, + { + D0, D0, /*........*/ + D2, D0, /*..#.....*/ + D7, D0, /*.###....*/ + D2, D4, /*..#..#..*/ + D2, D4, /*..#..#..*/ + D0, De, /*....###.*/ + D0, D4, /*.....#..*/ + D0, D0, /*........*/ + }, + }; + + unsigned char necmg_icon16x8[][32] = { + { + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + }, + { + D0, D0, D0, D0, /*................*/ + D0, D0, D3, D8, /*..........###...*/ + D0, D0, D7, De, /*.........######.*/ + Dc, D0, Df, D8, /*##......#####...*/ + D3, D3, D7, De, /*..##..##.######.*/ + D0, Dc, D3, D8, /*....##....###...*/ + D0, D0, D0, D0, /*................*/ + D0, D0, D0, D0, /*................*/ + }, + { + Df, Df, Df, Dc, /*##############..*/ + D8, D0, D0, D4, /*#............#..*/ + D8, D0, D0, D7, /*#............###*/ + D8, D0, D0, D1, /*#..............#*/ + D8, D0, D0, D1, /*#..............#*/ + D8, D0, D0, D7, /*#............###*/ + D8, D0, D0, D4, /*#............#..*/ + Df, Df, Df, Dc, /*##############..*/ + }, + { + Df, Df, Df, Dc, /*##############..*/ + D8, D0, D0, D4, /*#............#..*/ + Db, D0, D0, D7, /*#.##.........###*/ + Db, D0, D0, D1, /*#.##...........#*/ + Db, D0, D0, D1, /*# ##...........#*/ + Db, D0, D0, D7, /*#.##.........###*/ + D8, D0, D0, D4, /*#............#..*/ + Df, Df, Df, Dc, /*##############..*/ + }, + { + Df, Df, Df, Dc, /*##############..*/ + D8, D0, D0, D4, /*#............#..*/ + Db, Dc, D0, D7, /*#.####.......###*/ + Db, Dc, D0, D1, /*#.####.........#*/ + Db, Dc, D0, D1, /*# ####.........#*/ + Db, Dc, D0, D7, /*#.####.......###*/ + D8, D0, D0, D4, /*#............#..*/ + Df, Df, Df, Dc, /*##############..*/ + }, + { + Df, Df, Df, Dc, /*##############..*/ + D8, D0, D0, D4, /*#............#..*/ + Db, Df, D0, D7, /*#.######.....###*/ + Db, Df, D0, D1, /*#.######.......#*/ + Db, Df, D0, D1, /*# ######.......#*/ + Db, Df, D0, D7, /*#.######.....###*/ + D8, D0, D0, D4, /*#............#..*/ + Df, Df, Df, Dc, /*##############..*/ + }, + { + Df, Df, Df, Dc, /*##############..*/ + D8, D0, D0, D4, /*#............#..*/ + Db, Df, Dc, D7, /*#.########...###*/ + Db, Df, Dc, D1, /*#.########.....#*/ + Db, Df, Dc, D1, /*# ########.....#*/ + Db, Df, Dc, D7, /*#.########...###*/ + D8, D0, D0, D4, /*#............#..*/ + Df, Df, Df, Dc, /*##############..*/ + }, + { + Df, Df, Df, Dc, /*##############..*/ + D8, D0, D0, D4, /*#............#..*/ + Db, Df, Df, D7, /*#.##########.###*/ + Db, Df, Df, D1, /*#.##########...#*/ + Db, Df, Df, D1, /*# ##########...#*/ + Db, Df, Df, D7, /*#.##########.###*/ + D8, D0, D0, D4, /*#............#..*/ + Df, Df, Df, Dc, /*##############..*/ + }, + }; + #endif /* NECMG */ Index: PAO/sys/pc98/pc98/syscons.c diff -c PAO/sys/pc98/pc98/syscons.c:1.1.1.4 PAO/sys/pc98/pc98/syscons.c:1.1.1.4.2.1 *** PAO/sys/pc98/pc98/syscons.c:1.1.1.4 Sat Dec 5 05:42:59 1998 --- PAO/sys/pc98/pc98/syscons.c Sun Dec 6 07:49:25 1998 *************** *** 2558,2563 **** --- 2558,2564 ---- } s = spltty(); + #ifndef PC98 /* * With release 2.1 of the Xaccel server, the keyboard is left * hanging pretty often. Apparently an interrupt from the Index: PAO/sys/pccard/cardinfo.h diff -c PAO/sys/pccard/cardinfo.h:1.1.1.1 PAO/sys/pccard/cardinfo.h:1.1.1.1.4.1 *** PAO/sys/pccard/cardinfo.h:1.1.1.1 Fri Jul 24 19:26:31 1998 --- PAO/sys/pccard/cardinfo.h Sun Dec 6 07:49:29 1998 *************** *** 45,50 **** --- 45,52 ---- #define PIOCRWFLAG _IOW('P', 7, int) /* Set flags for drv use */ #define PIOCRWMEM _IOWR('P', 8, unsigned long) /* Set mem for drv use */ #define PIOCSPOW _IOW('P', 9, struct power) /* Set power structure */ + #define PIOCSVIR _IOW('P', 10, int) /* Virtual insert/remove */ + #define PIOCSBEEP _IOW('P', 11, int) /* Select Beep */ /* * Debug codes. */ *************** *** 54,60 **** /* * Slot states for PIOCGSTATE */ ! enum cardstate { noslot, empty, suspend, filled }; /* * Descriptor structure for memory map. --- 56,62 ---- /* * Slot states for PIOCGSTATE */ ! enum cardstate { noslot, empty, suspend, filled, inactive }; /* * Descriptor structure for memory map. *************** *** 136,140 **** --- 138,156 ---- #define NUM_MEM_WINDOWS 10 #define NUM_IO_WINDOWS 6 #define CARD_DEVICE "/dev/card%d" /* String for sprintf */ + + #ifdef PC98 + /* + * Mask of allowable interrupts. + * Ints are 3,5,6,10,12 + */ + #define PCCARD_INT_MASK_ALLOWED 0x1468 + #else /* PC98 */ + /* + * Mask of allowable interrupts. + * Ints are 3,4,5,7,9,10,11,12,14,15 + */ + #define PCCARD_INT_MASK_ALLOWED 0xDEB8 + #endif /* PC98 */ #endif /* !_PCCARD_CARDINFO_H_ */ Index: PAO/sys/pccard/cis.h diff -c PAO/sys/pccard/cis.h:1.1.1.1 PAO/sys/pccard/cis.h:1.1.1.1.8.1 *** PAO/sys/pccard/cis.h:1.1.1.1 Thu Dec 11 22:37:55 1997 --- PAO/sys/pccard/cis.h Sun Dec 6 07:49:30 1998 *************** *** 42,49 **** --- 42,58 ---- * are terminated with a 0xFF for the tuple code or * the tuple length. */ + #ifndef _PCCARD_CIS_H + #define _PCCARD_CIS_H + #define CIS_NULL 0 /* Empty tuple */ #define CIS_MEM_COMMON 0x01 /* Device descriptor, common memory */ + #define CIS_LONGLINK_CB 0x02 /* Long link to next chain for CardBus */ + #define CIS_INDIRECT 0x03 /* Indirect access */ + #define CIS_CONF_MAP_CB 0x04 /* Card Configuration map for CardBus */ + #define CIS_CONFIG_CB 0x05 /* Card Configuration entry for CardBus */ + #define CIS_LONGLINK_MFC 0x06 /* Long link to next chain for Multi function card */ + #define CIS_BAR 0x07 /* Base address register for CardBus */ #define CIS_CHECKSUM 0x10 /* Checksum */ #define CIS_LONGLINK_A 0x11 /* Link to Attribute memory */ #define CIS_LONGLINK_C 0x12 /* Link to Common memory */ *************** *** 247,249 **** --- 256,275 ---- #define CIS_MEM_LENSZ(x) (((x) >> 3) & 0x3) #define CIS_MEM_ADDRSZ(x) (((x) >> 5) & 0x3) #define CIS_MEM_HOST 0x80 + /* + * Misc sub-tuple. + * Byte 1: + * Byte 2: + * 0x0c - DMA Request Signal + * 00 - not support DMA + * 01 - use SPKR# line + * 10 - use IOIS16# line + * 11 - use INPACK# line + * 0x10 - DMA Width + * 0 - 8 bit DMA + * 1 - 16 bit DMA + */ + #define CIS_MISC_DMA_WIDTH(x) (((x) & 0x10) >> 4) + #define CIS_MISC_DMA_REQ(x) (((x) >> 2) & 0x3) + + #endif /* _PCCARD_CIS_H */ Index: PAO/sys/pccard/driver.h diff -c PAO/sys/pccard/driver.h:1.1.1.2 PAO/sys/pccard/driver.h:1.1.1.2.6.1 *** PAO/sys/pccard/driver.h:1.1.1.2 Sun Apr 5 07:20:48 1998 --- PAO/sys/pccard/driver.h Sun Dec 6 07:49:31 1998 *************** *** 16,24 **** int pccard_alloc_intr __P((u_int imask, inthand2_t *hand, int unit, u_int *maskp, u_int *pcic_imask)); #endif ! void pccard_configure __P((void)); void pccard_remove_driver __P((struct pccard_device *)); ! int pcic_probe __P((void)); /* XXX should be linker set */ enum beepstate { BEEP_ON, BEEP_OFF }; --- 16,34 ---- int pccard_alloc_intr __P((u_int imask, inthand2_t *hand, int unit, u_int *maskp, u_int *pcic_imask)); #endif ! void pccard_driver_init __P((void)); void pccard_remove_driver __P((struct pccard_device *)); ! ! /* new interrupt */ ! typedef void pccard_inthand_t(void *arg); ! ! struct pccard_int_desc { ! struct pccard_int_desc *next; ! pccard_inthand_t *handler; ! void *arg; ! unsigned *maskptr; ! unsigned mask; ! }; enum beepstate { BEEP_ON, BEEP_OFF }; *************** *** 26,31 **** void pccard_remove_beep __P((void)); void pccard_success_beep __P((void)); void pccard_failure_beep __P((void)); ! void pccard_beep_select __P((enum beepstate)); #endif /* !_PCCARD_DRIVER_H_ */ --- 36,45 ---- void pccard_remove_beep __P((void)); void pccard_success_beep __P((void)); void pccard_failure_beep __P((void)); ! int pccard_beep_select __P((int)); ! ! #ifdef KERNEL ! void pccard_configure __P((void)); ! #endif /* KERNEL */ #endif /* !_PCCARD_DRIVER_H_ */ Index: PAO/sys/pccard/i82365.h diff -c PAO/sys/pccard/i82365.h:1.1.1.2 PAO/sys/pccard/i82365.h:1.1.1.2.6.1 *** PAO/sys/pccard/i82365.h:1.1.1.2 Sun Apr 5 07:20:49 1998 --- PAO/sys/pccard/i82365.h Sun Dec 6 07:49:32 1998 *************** *** 1,224 **** - /* - * i82365.h - Definitions for Intel 82365 PCIC - * PCMCIA Card Interface Controller - * - * originally by Barry Jaspan; hacked over by Keith Moore - * hacked to unrecognisability by Andrew McRae (andrew@mega.com.au) - * - * Updated 3/3/95 to include Cirrus Logic stuff. - *------------------------------------------------------------------------- - * - * Copyright (c) 1995 Andrew McRae. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - #define PCIC_I82365 0 /* Intel chip */ - #define PCIC_IBM 1 /* IBM clone */ - #define PCIC_VLSI 2 /* VLSI chip */ - #define PCIC_PD672X 3 /* Cirrus logic 627x */ - #define PCIC_PD6710 4 /* Cirrus logic 6710 */ - #define PCIC_CL6729 5 /* Cirrus logic 6729 */ - #define PCIC_VG468 6 /* Vadem 468 */ - #define PCIC_VG469 7 /* Vadem 469 */ - #define PCIC_RF5C396 8 /* Ricoh RF5C396 */ - #define PCIC_IBM_KING 9 /* IBM KING PCMCIA Controller */ - #define PCIC_PC98 10 /* NEC PC98 PCMCIA Controller */ - #define PCIC_TI1130 11 /* TI PCI1130 CardBus */ - - /* - * Address of the controllers. Each controller can manage - * two PCMCIA slots. Up to 8 slots are supported in total. - * The PCIC controller is accessed via an index port and a - * data port. The index port has the 8 bit address of the - * register accessed via the data port. How I long for - * real memory mapped I/O! - * The top two bits of the index address are used to - * identify the port number, and the lower 6 bits - * select one of the 64 possible data registers. - */ - #define PCIC_INDEX_0 0x3E0 /* index reg, chips 0 and 1 */ - #define PCIC_DATA_0 (PCIC_INDEX_0 + 1) /* data reg, chips 0 and 1 */ - #define PCIC_INDEX_1 (PCIC_INDEX_0 + 2) /* index reg, chips 2 and 3 */ - #define PCIC_DATA_1 (PCIC_INDEX_1 + 1) /* data reg, chips 2 and 3 */ - /* - * Register index addresses. - */ - #define PCIC_ID_REV 0x00 /* Identification and Revision */ - #define PCIC_STATUS 0x01 /* Interface Status */ - #define PCIC_POWER 0x02 /* Power and RESETDRV control */ - #define PCIC_INT_GEN 0x03 /* Interrupt and General Control */ - #define PCIC_STAT_CHG 0x04 /* Card Status Change */ - #define PCIC_STAT_INT 0x05 /* Card Status Change Interrupt Config */ - #define PCIC_ADDRWINE 0x06 /* Address Window Enable */ - #define PCIC_IOCTL 0x07 /* I/O Control */ - #define PCIC_IO0 0x08 /* I/O Address 0 */ - #define PCIC_IO1 0x0c /* I/O Address 1 */ - #define PCIC_MEMBASE 0x10 /* Base of memory window registers */ - #define PCIC_CDGC 0x16 /* Card Detect and General Control */ - #define PCIC_MISC1 0x16 /* PD672x: Misc control register 1 per slot */ - #define PCIC_GLO_CTRL 0x1e /* Global Control Register */ - #define PCIC_MISC2 0x1e /* PD672x: Misc control register 2 per chip */ - - #define PCIC_TIME_SETUP0 0x3a - #define PCIC_TIME_CMD0 0x3b - #define PCIC_TIME_RECOV0 0x3c - #define PCIC_TIME_SETUP1 0x3d - #define PCIC_TIME_CMD1 0x3e - #define PCIC_TIME_RECOV1 0x3f - - #define PCIC_SLOT_SIZE 0x40 /* Size of register set for one slot */ - - /* Now register bits, ordered by reg # */ - - /* For Identification and Revision (PCIC_ID_REV) */ - #define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */ - #define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */ - #define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ - #define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ - #define PCIC_IBM3 0x8a /* IBM KING PCIC clone; Both Memory and I/O */ - - /* For Interface Status register (PCIC_STATUS) */ - #define PCIC_VPPV 0x80 /* Vpp_valid */ - #define PCIC_POW 0x40 /* PC Card power active */ - #define PCIC_READY 0x20 /* Ready/~Busy */ - #define PCIC_MWP 0x10 /* Memory Write Protect */ - #define PCIC_CD 0x0C /* Both card detect bits */ - #define PCIC_BVD 0x03 /* Both Battery Voltage Detect bits */ - - /* For the Power and RESETDRV register (PCIC_POWER) */ - #define PCIC_OUTENA 0x80 /* Output Enable */ - #define PCIC_DISRST 0x40 /* Disable RESETDRV */ - #define PCIC_APSENA 0x20 /* Auto Pwer Switch Enable */ - #define PCIC_PCPWRE 0x10 /* PC Card Power Enable */ - #define PCIC_VCC 0x18 /* Vcc control bits */ - #define PCIC_VCC_5V 0x10 /* 5 volts */ - #define PCIC_VCC_3V 0x18 /* 3 volts */ - #define PCIC_VCC_5V_KING 0x14 /* 5 volts for KING PCIC */ - #define PCIC_VPP 0x0C /* Vpp control bits */ - #define PCIC_VPP_5V 0x01 /* 5 volts */ - #define PCIC_VPP_12V 0x02 /* 12 volts */ - - /* For the Interrupt and General Control register (PCIC_INT_GEN) */ - #define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */ - #define PCIC_IOCARD 0x20 - #define PCIC_MEMCARD 0x00 - #define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */ - #define PCIC_INTR_ENA 0x10 /* Interrupt enable */ - - /* For the Card Status Change register (PCIC_STAT_CHG) */ - #define PCIC_CDTCH 0x08 /* Card Detect Change */ - #define PCIC_RDYCH 0x04 /* Ready Change */ - #define PCIC_BATWRN 0x02 /* Battery Warning */ - #define PCIC_BATDED 0x01 /* Battery Dead */ - - /* - * For the Address Window Enable Register (PCIC_ADDRWINE) - * The lower 6 bits contain enable bits for the memory - * windows (LSB = memory window 0). - */ - #define PCIC_MEMCS16 0x20 /* ~MEMCS16 Decode A23-A12 */ - #define PCIC_IO0_EN 0x40 /* I/O Window 0 Enable */ - #define PCIC_IO1_EN 0x80 /* I/O Window 1 Enable */ - - /* - * For the I/O Control Register (PCIC_IOCTL) - * The lower nybble is the flags for I/O window 0 - * The upper nybble is the flags for I/O window 1 - */ - #define PCIC_IO_16BIT 0x01 /* I/O to this segment is 16 bit */ - #define PCIC_IO_CS16 0x02 /* I/O cs16 source is the card */ - #define PCIC_IO_0WS 0x04 /* zero wait states added on 8 bit cycles */ - #define PCIC_IO_WS 0x08 /* Wait states added for 16 bit cycles */ - - /* - * The memory window registers contain the start and end - * physical host address that the PCIC maps to the card, - * and an offset calculated from the card memory address. - * All values are shifted down 12 bits, so allocation is - * done in 4Kb blocks. Only 12 bits of each value is - * stored, limiting the range to the ISA address size of - * 24 bits. The upper 4 bits of the most significant byte - * within the values are used for various flags. - * - * The layout is: - * - * base+0 : lower 8 bits of system memory start address - * base+1 : upper 4 bits of system memory start address + flags - * base+2 : lower 8 bits of system memory end address - * base+3 : upper 4 bits of system memory end address + flags - * base+4 : lower 8 bits of offset to card address - * base+5 : upper 4 bits of offset to card address + flags - * - * The following two bytes are reserved for other use. - */ - #define PCIC_MEMSIZE 8 - /* - * Flags for system memory start address upper byte - */ - #define PCIC_ZEROWS 0x40 /* Zero wait states */ - #define PCIC_DATA16 0x80 /* Data width is 16 bits */ - - /* - * Flags for system memory end address upper byte - */ - #define PCIC_MW0 0x40 /* Wait state bit 0 */ - #define PCIC_MW1 0x80 /* Wait state bit 1 */ - - /* - * Flags for card offset upper byte - */ - #define PCIC_REG 0x40 /* Attribute/Common select (why called Reg?) */ - #define PCIC_WP 0x80 /* Write-protect this window */ - - /* For Card Detect and General Control register (PCIC_CDGC) */ - #define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */ - #define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */ - #define PCIC_GPI_EN 0x04 /* GPI Enable */ - #define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */ - #define PCIC_CDRES_EN 0x10 /* card detect resume enable */ - #define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */ - - /* For Misc. Control Register 1 */ - #define PCIC_SPKR_EN 0x10 /* Cirrus PD672x: speaker enable */ - - /* For Global Control register (PCIC_GLO_CTRL) */ - #define PCIC_PWR_DOWN 0x01 /* power down */ - #define PCIC_LVL_MODE 0x02 /* level mode interrupt enable */ - #define PCIC_WB_CSCINT 0x04 /* explicit write-back csc intr */ - #define PCIC_IRQ0_LEVEL 0x08 /* irq 14 pulse mode enable */ - #define PCIC_IRQ1_LEVEL 0x10 - - /* For Misc. Control Register 2 */ - #define PCIC_LPDM_EN 0x02 /* Cirrus PD672x: low power dynamic mode */ - - /* - * Mask of allowable interrupts. - * Ints are 3,4,5,7,9,10,11,12,14,15 - */ - #define PCIC_INT_MASK_ALLOWED 0xDEB8 - - #define PCIC_IO_WIN 2 - #define PCIC_MEM_WIN 5 - - #define PCIC_MAX_SLOTS 8 --- 0 ---- Index: PAO/sys/pccard/i82365reg.h diff -c /dev/null PAO/sys/pccard/i82365reg.h:1.1.6.1 *** /dev/null Fri Dec 25 10:52:04 1998 --- PAO/sys/pccard/i82365reg.h Sun Dec 6 07:49:33 1998 *************** *** 0 **** --- 1,220 ---- + /* + * i82365reg.h - Definitions for Intel 82365 PCIC + * PCMCIA Card Interface Controller + * + * originally by Barry Jaspan; hacked over by Keith Moore + * hacked to unrecognisability by Andrew McRae (andrew@mega.com.au) + * + * Updated 3/3/95 to include Cirrus Logic stuff. + *------------------------------------------------------------------------- + * + * Copyright (c) 1995 Andrew McRae. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + #ifndef _PCCARD_I82365REG_H + #define _PCCARD_I82365REG_H + + /* + * Register index addresses. + */ + #define PCIC_ID_REV 0x00 /* Identification and Revision */ + #define PCIC_STATUS 0x01 /* Interface Status */ + #define PCIC_POWER 0x02 /* Power and RESETDRV control */ + #define PCIC_INT_GEN 0x03 /* Interrupt and General Control */ + #define PCIC_STAT_CHG 0x04 /* Card Status Change */ + #define PCIC_STAT_INT 0x05 /* Card Status Change Interrupt Config */ + #define PCIC_ADDRWINE 0x06 /* Address Window Enable */ + #define PCIC_IOCTL 0x07 /* I/O Control */ + #define PCIC_IO0 0x08 /* I/O Address 0 */ + #define PCIC_IO1 0x0c /* I/O Address 1 */ + #define PCIC_MEMBASE0 0x10 /* Base of memory window registers */ + #define PCIC_CDGC 0x16 /* Card Detect and General Control */ + #define PCIC_MEMBASE1 0x18 /* Base of memory window registers */ + #define PCIC_MISC1 0x16 /* PD672x: Misc control register 1 per slot */ + #define PCIC_GLO_CTRL 0x1e /* Global Control Register */ + #define PCIC_MISC2 0x1e /* PD672x: Misc control register 2 per chip */ + #define PCIC_MEMBASE2 0x20 /* Base of memory window registers */ + #define PCIC_MEMBASE3 0x28 /* Base of memory window registers */ + #define PCIC_MEMBASE4 0x30 /* Base of memory window registers */ + #define PCIC_MEMBASEU0 0x40 /* Base of memory window (upper/optional) */ + #define PCIC_MEMBASEU1 0x41 /* Base of memory window (upper/optional) */ + #define PCIC_MEMBASEU2 0x42 /* Base of memory window (upper/optional) */ + #define PCIC_MEMBASEU3 0x43 /* Base of memory window (upper/optional) */ + #define PCIC_MEMBASEU4 0x44 /* Base of memory window (upper/optional) */ + + #define PCIC_TIME_SETUP0 0x3a + #define PCIC_TIME_CMD0 0x3b + #define PCIC_TIME_RECOV0 0x3c + #define PCIC_TIME_SETUP1 0x3d + #define PCIC_TIME_CMD1 0x3e + #define PCIC_TIME_RECOV1 0x3f + + #define PCIC_SLOT_SIZE 0x40 /* Size of register set for one slot */ + + /* Now register bits, ordered by reg # */ + + /* For Identification and Revision (PCIC_ID_REV) */ + #define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */ + #define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */ + #define PCIC_INTEL2 0x84 /* Intel 82365SL DF or VLSI; Both Memory and I/O */ + #define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ + #define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ + #define PCIC_IBM3 0x8a /* IBM KING PCIC clone; Both Memory and I/O */ + + /* For Interface Status register (PCIC_STATUS) */ + #define PCIC_VPPV 0x80 /* Vpp_valid */ + #define PCIC_POW 0x40 /* PC Card power active */ + #define PCIC_READY 0x20 /* Ready/~Busy */ + #define PCIC_MWP 0x10 /* Memory Write Protect */ + #define PCIC_CD 0x0C /* Both card detect bits */ + #define PCIC_BVD 0x03 /* Both Battery Voltage Detect bits */ + + /* For the Power and RESETDRV register (PCIC_POWER) */ + #define PCIC_OUTENA 0x80 /* Output Enable */ + #define PCIC_DISRST 0x40 /* Disable RESETDRV */ + #define PCIC_APSENA 0x20 /* Auto Pwer Switch Enable */ + #define PCIC_PCPWRE 0x10 /* PC Card Power Enable */ + #define PCIC_VCC 0x18 /* Vcc control bits */ + #define PCIC_VCC_5V 0x10 /* 5 volts */ + #define PCIC_VCC_3V 0x18 /* 3 volts */ + #define PCIC_VCC_5V_KING 0x14 /* 5 volts for KING PCIC */ + #define PCIC_VPP 0x0C /* Vpp control bits */ + #define PCIC_VPP_5V 0x01 /* 5 volts */ + #define PCIC_VPP_12V 0x02 /* 12 volts */ + + /* For the Interrupt and General Control register (PCIC_INT_GEN) */ + #define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */ + #define PCIC_IOCARD 0x20 + #define PCIC_MEMCARD 0x00 + #define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */ + #define PCIC_INTR_ENA 0x10 /* Interrupt enable */ + + /* For the Card Status Change register (PCIC_STAT_CHG) */ + #define PCIC_CDTCH 0x08 /* Card Detect Change */ + #define PCIC_RDYCH 0x04 /* Ready Change */ + #define PCIC_BATWRN 0x02 /* Battery Warning */ + #define PCIC_BATDED 0x01 /* Battery Dead */ + + /* + * For the Address Window Enable Register (PCIC_ADDRWINE) + * The lower 6 bits contain enable bits for the memory + * windows (LSB = memory window 0). + */ + #define PCIC_MEMCS16 0x20 /* ~MEMCS16 Decode A23-A12 */ + #define PCIC_IO0_EN 0x40 /* I/O Window 0 Enable */ + #define PCIC_IO1_EN 0x80 /* I/O Window 1 Enable */ + + /* + * For the I/O Control Register (PCIC_IOCTL) + * The lower nybble is the flags for I/O window 0 + * The upper nybble is the flags for I/O window 1 + */ + #define PCIC_IO_16BIT 0x01 /* I/O to this segment is 16 bit */ + #define PCIC_IO_CS16 0x02 /* I/O cs16 source is the card */ + #define PCIC_IO_0WS 0x04 /* zero wait states added on 8 bit cycles */ + #define PCIC_IO_WS 0x08 /* Wait states added for 16 bit cycles */ + + /* + * The memory window registers contain the start and end + * physical host address that the PCIC maps to the card, + * and an offset calculated from the card memory address. + * All values are shifted down 12 bits, so allocation is + * done in 4Kb blocks. Only 12 bits of each value is + * stored, limiting the range to the ISA address size of + * 24 bits. The upper 4 bits of the most significant byte + * within the values are used for various flags. + * + * The layout is: + * + * base+0 : lower 8 bits of system memory start address + * base+1 : upper 4 bits of system memory start address + flags + * base+2 : lower 8 bits of system memory end address + * base+3 : upper 4 bits of system memory end address + flags + * base+4 : lower 8 bits of offset to card address + * base+5 : upper 4 bits of offset to card address + flags + * + * The following two bytes are reserved for other use. + */ + #define PCIC_MEMSIZE 8 + /* + * Flags for system memory start address upper byte + */ + #define PCIC_ZEROWS 0x40 /* Zero wait states */ + #define PCIC_DATA16 0x80 /* Data width is 16 bits */ + + /* + * Flags for system memory end address upper byte + */ + #define PCIC_MW0 0x40 /* Wait state bit 0 */ + #define PCIC_MW1 0x80 /* Wait state bit 1 */ + + /* + * Flags for card offset upper byte + */ + #define PCIC_REG 0x40 /* Attribute/Common select (why called Reg?) */ + #define PCIC_WP 0x80 /* Write-protect this window */ + + /* For Card Detect and General Control register (PCIC_CDGC) */ + #define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */ + #define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */ + #define PCIC_GPI_EN 0x04 /* GPI Enable */ + #define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */ + #define PCIC_CDRES_EN 0x10 /* card detect resume enable */ + #define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */ + + /* For Misc. Control Register 1 */ + #define PCIC_SPKR_EN 0x10 /* Cirrus PD672x: speaker enable */ + + /* For Global Control register (PCIC_GLO_CTRL) */ + #define PCIC_PWR_DOWN 0x01 /* power down */ + #define PCIC_LVL_MODE 0x02 /* level mode interrupt enable */ + #define PCIC_WB_CSCINT 0x04 /* explicit write-back csc intr */ + #define PCIC_IRQ0_LEVEL 0x08 /* irq 14 pulse mode enable */ + #define PCIC_IRQ1_LEVEL 0x10 + + /* For Misc. Control Register 2 */ + #define PCIC_LPDM_EN 0x02 /* Cirrus PD672x: low power dynamic mode */ + + /* Cirrus Logic PD-672X specific index */ + + #define CL672X_PCIC_MISC1 0x16 /* Misc Control 1 */ + #define CL672X_PCIC_MISC2 0x1e /* Misc Control 2 */ + + /* Misc 1 regs. */ + #define CL672X_M1_5V_DET 0x01 /* 5v detect */ + #define CL672X_M1_SPKR_EN 0x10 /* Speaker Enable */ + /* Misc 2 regs. */ + #define CL672X_M2_LPDM_EN 0x02 /* Low power dynamic mode */ + + /* Vadem VG469 specific index */ + #define VG469_VSENSE 0x1f /* Card voltage sense */ + + /* Flags for VG469_VSENSE */ + #define VG469_VSENSE_A_VS1 0x01 + #define VG469_VSENSE_A_VS2 0x02 + #define VG469_VSENSE_B_VS1 0x04 + #define VG469_VSENSE_B_VS2 0x08 + + #endif /* _PCCARD_I82365REG_H */ Index: PAO/sys/pccard/paoversion.h diff -c /dev/null PAO/sys/pccard/paoversion.h:1.1.2.1 *** /dev/null Fri Dec 25 10:52:05 1998 --- PAO/sys/pccard/paoversion.h Fri Dec 25 10:46:43 1998 *************** *** 0 **** --- 1,4 ---- + /* + * $Id: paoversion.h,v 1.1.2.1 1998/12/25 01:46:43 hosokawa Exp $ + */ + #define PAO_VERSION "PAO-19981225" Index: PAO/sys/pccard/pccard.c diff -c PAO/sys/pccard/pccard.c:1.1.1.4 PAO/sys/pccard/pccard.c:1.1.1.4.2.3 *** PAO/sys/pccard/pccard.c:1.1.1.4 Sat Dec 5 05:43:04 1998 --- PAO/sys/pccard/pccard.c Fri Dec 25 10:46:43 1998 *************** *** 53,66 **** --- 53,75 ---- #include #include #include + #include #include + #ifdef NECMG + #include + #endif + /* * XXX We shouldn't be using processor-specific/bus-specific code in * here, but we need the start of the ISA hole (IOM_BEGIN). */ + #ifdef PC98 + #include + #else /*PC98*/ #include + #endif /*PC98*/ SYSCTL_NODE(_machdep, OID_AUTO, pccard, CTLFLAG_RW, 0, "pccard"); *************** *** 78,83 **** --- 87,93 ---- #define MIN(a,b) ((a)<(b)?(a):(b)) + static u_int build_freelist(u_int); static int allocate_driver(struct slot *, struct dev_desc *); static void inserted(void *); static void unregister_device_interrupt(struct pccard_devinfo *); *************** *** 86,92 **** --- 96,104 ---- static struct pccard_device *find_driver(char *); static void remove_device(struct pccard_devinfo *); static void slot_irq_handler(int); + #if 0 static void power_off_slot(void *); + #endif #if NAPM > 0 /* *************** *** 102,109 **** #endif /* NAPM > 0 */ static struct slot *pccard_slots[MAXSLOT]; /* slot entries */ ! static struct slot *slot_list; ! static struct slot_ctrl *cont_list; static struct pccard_device *drivers; /* Card drivers */ /* --- 114,120 ---- #endif /* NAPM > 0 */ static struct slot *pccard_slots[MAXSLOT]; /* slot entries */ ! static struct slot_ctrl *cont_list = NULL; static struct pccard_device *drivers; /* Card drivers */ /* *************** *** 127,132 **** --- 138,166 ---- crdioctl, nostop, nullreset, nodevtotty,/* pcmcia */ crdselect, nommap, NULL, "crd", NULL, -1 }; + /* + * Setup PC-card support for all PC-card drivers + */ + void + pccard_driver_init(void) + { + struct pccard_device **p_drvp; + struct pccard_device *p_drv; + static int already_configured = 0; + + if (already_configured) + return; + already_configured = 1; + + p_drvp = (struct pccard_device **)pccarddrv_set.ls_items; + printf("PAO version: %s\n", PAO_VERSION); + printf("Initializing PC-card drivers: "); + while ((p_drv = *p_drvp++)) { + printf("%s ", p_drv->name); + pccard_add_driver(p_drv); + } + printf("\n"); + } /* * pccard_configure - called by autoconf code. *************** *** 138,160 **** * that it sees, and these are mapped to a master * slot number accessed via the character device entries. */ ! void ! pccard_configure(void) { ! struct pccard_device **drivers, *drv; ! #include "pcic.h" ! #if NPCIC > 0 ! pcic_probe(); #endif ! drivers = (struct pccard_device **)pccarddrv_set.ls_items; ! printf("Initializing PC-card drivers:"); ! while ((drv = *drivers++)) { ! printf(" %s", drv->name); ! pccard_add_driver(drv); } - printf("\n"); } /* --- 172,231 ---- * that it sees, and these are mapped to a master * slot number accessed via the character device entries. */ ! static void ! nullfunc(int unit) { ! /* empty */ ! } ! static u_int ! build_freelist(u_int pcic_mask) ! { ! int irq; ! u_int mask, freemask; ! ! /* No free IRQs (yet). */ ! freemask = 0; ! ! /* Walk through all of the IRQ's and find any that aren't allocated. */ ! for (irq = 0; irq < ICU_LEN; irq++) { ! /* ! * If the PCIC controller can't generate it, don't ! * bother checking to see if it it's free. ! */ ! mask = 1 << irq; ! if (!(mask & pcic_mask)) continue; ! ! /* See if the IRQ is free. */ ! if (register_intr(irq, 0, 0, nullfunc, NULL, irq) == 0) { ! /* Give it back, but add it to the mask */ ! INTRMASK(freemask, mask); ! unregister_intr(irq, nullfunc); ! } ! } ! #ifdef PCIC_DEBUG ! printf("Freelist of IRQ's <0x%x>\n", freemask); #endif + return freemask; + } ! void ! pccard_configure(void) ! { ! static int already_configured = 0; ! u_int free_irqs; ! int i; ! ! if (already_configured) ! return; ! already_configured = 1; ! ! /* Determine the list of free interrupts */ ! free_irqs = build_freelist(PCCARD_INT_MASK_ALLOWED); /*XXX*/ ! for (i = 0; i < MAXSLOT; i++) { ! if (pccard_slots[i] && pccard_slots[i]->ctrl) ! pccard_slots[i]->ctrl->irqs = free_irqs; } } /* *************** *** 175,181 **** drivers = drv; } - #ifdef unused /* * pccard_remove_driver - called to unlink driver * from devices. Usually called when drivers are --- 246,251 ---- *************** *** 184,199 **** void pccard_remove_driver(struct pccard_device *drv) { struct slot *slt; ! struct pccard_devinfo *devi, *next; struct pccard_device *drvlist; ! for (slt = slot_list; slt; slt = slt->next) ! for (devi = slt->devices; devi; devi = next) { ! next = devi->next; ! if (devi->drv == drv) ! remove_device(devi); ! } /* * Once all the devices belonging to this driver have been * freed, then remove the driver from the list --- 254,270 ---- void pccard_remove_driver(struct pccard_device *drv) { + struct slot_ctrl *cinfo; struct slot *slt; ! struct pccard_devinfo *devi; struct pccard_device *drvlist; ! for (cinfo = cont_list; cinfo; cinfo = cinfo->next) ! for (slt = cinfo->slot_list; slt; slt = slt->next) ! for (devi = slt->devices; devi; devi = devi->next) { ! if (devi->drv == drv) ! remove_device(devi); ! } /* * Once all the devices belonging to this driver have been * freed, then remove the driver from the list *************** *** 208,214 **** break; } } ! #endif /* * pccard_remove_controller - Called when the slot --- 279,304 ---- break; } } ! ! /* ! * pccard_add_controller - link it into the ! * list of controllers. ! */ ! void ! pccard_add_controller(struct slot_ctrl *ctrl) ! { ! static int unit = 0; ! ! ctrl->next = cont_list; ! cont_list = ctrl; ! ctrl->slot_list = NULL; ! if (ctrl->maxmem > NUM_MEM_WINDOWS) ! ctrl->maxmem = NUM_MEM_WINDOWS; ! if (ctrl->maxio > NUM_IO_WINDOWS) ! ctrl->maxio = NUM_IO_WINDOWS; ! printf("PC-Card ctlr(%d) %s (%d mem & %d I/O windows)\n", ! unit++, ctrl->name, ctrl->maxmem, ctrl->maxio); ! } /* * pccard_remove_controller - Called when the slot *************** *** 220,267 **** void pccard_remove_controller(struct slot_ctrl *ctrl) { ! struct slot *slt, *next, *last = 0; struct slot_ctrl *cl; struct pccard_devinfo *devi; ! for (slt = slot_list; slt; slt = next) { ! next = slt->next; /* ! * If this slot belongs to this controller, ! * remove this slot. */ ! if (slt->ctrl == ctrl) { ! pccard_slots[slt->slotnum] = 0; ! if (slt->insert_seq) ! untimeout(inserted, (void *)slt); ! /* ! * Unload the drivers attached to this slot. ! */ ! while (devi = slt->devices) ! remove_device(devi); ! /* ! * Disable the slot and unlink the slot from the ! * slot list. ! */ ! disable_slot(slt); ! if (last) ! last->next = next; ! else ! slot_list = next; #if NAPM > 0 ! apm_hook_disestablish(APM_HOOK_SUSPEND, ! &s_hook[slt->slotnum]); ! apm_hook_disestablish(APM_HOOK_RESUME, ! &r_hook[slt->slotnum]); ! #endif ! if (ctrl->extra && slt->cdata) ! FREE(slt->cdata, M_DEVBUF); ! FREE(slt, M_DEVBUF); ! /* ! * Can't use slot after we have freed it. ! */ ! } else { ! last = slt; } } /* --- 310,347 ---- void pccard_remove_controller(struct slot_ctrl *ctrl) { ! struct slot *slt; struct slot_ctrl *cl; struct pccard_devinfo *devi; ! for (cl = cont_list; cl; cl = cl->next) { /* ! * remove all slot belong this controller. */ ! if (cl == ctrl) { ! for (slt = cl->slot_list; slt; slt = slt->next) { ! pccard_slots[slt->slotnum] = 0; ! if (slt->insert_seq) ! untimeout(inserted, (void *)slt); ! /* ! * Unload the drivers attached to this slot. ! */ ! while (devi = slt->devices) ! remove_device(devi); ! /* ! * Disable the slot. ! */ ! disable_slot(slt); #if NAPM > 0 ! apm_hook_disestablish(APM_HOOK_SUSPEND, ! &s_hook[slt->slotnum]); ! apm_hook_disestablish(APM_HOOK_RESUME, ! &r_hook[slt->slotnum]); ! #endif ! if (ctrl->extra && slt->cdata) ! FREE(slt->cdata, M_DEVBUF); ! FREE(slt, M_DEVBUF); ! } } } /* *************** *** 277,282 **** --- 357,370 ---- } } + static void + really_power_off_slot(void *arg) + { + struct slot *slt = (struct slot *)arg; + slt->ctrl->disable(slt); + } + + #if 0 /* * Power off the slot. * (doing it immediately makes the removal of some cards unstable) *************** *** 288,295 **** --- 376,390 ---- /* Power off the slot. */ slt->pwr_off_pending = 0; + #if 1 + /* power off the slot 1/2 seconds after removal of cards */ + timeout(really_power_off_slot, (caddr_t)slt, hz / 2); + slt->pwr_off_pending = 1; + #else slt->ctrl->disable(slt); + #endif } + #endif /* * unregister_device_interrupt - Disable the interrupt generation to *************** *** 303,311 **** if (devi->running) { s = splhigh(); ! devi->drv->disable(devi); devi->running = 0; ! if (devi->isahd.id_irq && --slt->irqref <= 0) { printf("Return IRQ=%d\n",slt->irq); slt->ctrl->mapirq(slt, 0); INTRDIS(1<irq); --- 398,411 ---- if (devi->running) { s = splhigh(); ! /* ! * 'running' is equal to 2 when an IRQ has been mapped and ! * the device enable function has returned an error. ! */ ! if(devi->running != 2) ! devi->drv->disable(devi); devi->running = 0; ! if (devi->pd_irq && --slt->irqref <= 0) { printf("Return IRQ=%d\n",slt->irq); slt->ctrl->mapirq(slt, 0); INTRDIS(1<irq); *************** *** 321,326 **** --- 421,463 ---- } } + #ifdef CB_TEST + /* new shared interrupt routine */ + + #define PCCARD_MAX_IRQ ICU_LEN + struct pccard_int_desc *pccard_int_desc[PCCARD_MAX_IRQ]; + + #ifndef NO_SHARED_IRQ + + static inline unsigned + splq (unsigned mask) + { + unsigned temp=cpl; + cpl |= mask; + return temp; + } + + static void + pccard_int (int irq) + { + struct pccard_int_desc * p; + int s; + + if (irq<0 || irq >= PCCARD_MAX_IRQ) { + printf ("pccard_int: irq %d out of range, ignored\n", irq); + return; + }; + for (p = pccard_int_desc[irq]; p!=NULL; p=p->next) { + s = splq (*p->maskptr); + (*p->handler) (p->arg); + /* p->tally++; */ + splx (s); + }; + } + #endif + + #endif /* CB_TEST */ + /* * disable_slot - Disables the slot by removing * the power and unmapping the I/O *************** *** 341,351 **** * driver is accessing the device and it is removed, then * all bets are off... */ for (devi = slt->devices; devi; devi = devi->next) unregister_device_interrupt(devi); /* Power off the slot 1/2 second after removal of the card */ ! timeout(power_off_slot, (caddr_t)slt, hz / 2); slt->pwr_off_pending = 1; /* De-activate all contexts. */ --- 478,496 ---- * driver is accessing the device and it is removed, then * all bets are off... */ + #ifdef NECMG + /* + * XXX, + * Unload/load wd driver cause double fault in dscheck() + * after resume. That is generic BUG. + */ + #else /* !NECMG */ for (devi = slt->devices; devi; devi = devi->next) unregister_device_interrupt(devi); + #endif /* !NECMG */ /* Power off the slot 1/2 second after removal of the card */ ! timeout(really_power_off_slot, (caddr_t)slt, hz / 2); slt->pwr_off_pending = 1; /* De-activate all contexts. */ *************** *** 382,388 **** * Disable any pending timeouts for this slot since we're * powering it down/disabling now. */ ! untimeout(power_off_slot, (caddr_t)slt); slt->ctrl->disable(slt); return (0); } --- 527,533 ---- * Disable any pending timeouts for this slot since we're * powering it down/disabling now. */ ! untimeout(really_power_off_slot, (caddr_t)slt); slt->ctrl->disable(slt); return (0); } *************** *** 398,405 **** --- 543,558 ---- if (slt->state == suspend) { slt->state = empty; slt->insert_seq = 1; + #ifdef NECMG + /* + * Lock out access to wd controler. + */ + DELAY(250*1000); + inserted((void*)slt); + #else /* NECMG */ timeout(inserted, (void *)slt, hz/4); selwakeup(&slt->selp); + #endif /* !NECMG */ } return (0); } *************** *** 437,458 **** slt->ctrl = ctrl; slt->slotnum = slotno; pccard_slots[slotno] = slt; ! slt->next = slot_list; ! slot_list = slt; ! /* ! * If this controller hasn't been seen before, then ! * link it into the list of controllers. ! */ ! if (ctrl->slots++ == 0) { ! ctrl->next = cont_list; ! cont_list = ctrl; ! if (ctrl->maxmem > NUM_MEM_WINDOWS) ! ctrl->maxmem = NUM_MEM_WINDOWS; ! if (ctrl->maxio > NUM_IO_WINDOWS) ! ctrl->maxio = NUM_IO_WINDOWS; ! printf("PC-Card %s (%d mem & %d I/O windows)\n", ! ctrl->name, ctrl->maxmem, ctrl->maxio); ! } #if NAPM > 0 { struct apmhook *ap; --- 590,597 ---- slt->ctrl = ctrl; slt->slotnum = slotno; pccard_slots[slotno] = slt; ! slt->next = ctrl->slot_list; ! ctrl->slot_list = slt; #if NAPM > 0 { struct apmhook *ap; *************** *** 483,492 **** pccard_alloc_intr(u_int imask, inthand2_t *hand, int unit, u_int *maskp, u_int *pcic_imask) { ! int irq; unsigned int mask; ! for (irq = 1; irq < ICU_LEN; irq++) { mask = 1ul << irq; if (!(mask & imask)) continue; --- 622,633 ---- pccard_alloc_intr(u_int imask, inthand2_t *hand, int unit, u_int *maskp, u_int *pcic_imask) { ! int irq, minirq, maxirq; unsigned int mask; ! minirq = 1; ! maxirq = ICU_LEN - 1; ! for (irq = minirq; irq <= maxirq; irq++) { mask = 1ul << irq; if (!(mask & imask)) continue; *************** *** 526,532 **** * then reject the request. */ for (devi = slt->devices; devi; devi = devi->next) ! if (devi->drv == drv && devi->isahd.id_unit == desc->unit) { if (devi->running) return(EBUSY); remove_device(devi); --- 667,673 ---- * then reject the request. */ for (devi = slt->devices; devi; devi = devi->next) ! if (devi->drv == drv && devi->pd_unit == desc->unit) { if (devi->running) return(EBUSY); remove_device(devi); *************** *** 537,547 **** * against the slot interrupt (if one has been allocated). */ if (desc->irqmask && drv->imask) { ! if ((slt->ctrl->irqs & desc->irqmask) == 0) return(EINVAL); if (slt->irq) { ! if (((1 << slt->irq) & desc->irqmask) == 0) return(EINVAL); slt->irqref++; irq = slt->irq; } else { --- 678,692 ---- * against the slot interrupt (if one has been allocated). */ if (desc->irqmask && drv->imask) { ! if ((slt->ctrl->irqs & desc->irqmask)==0) { ! printf("crd: slot_ctrl IRQ mask mismatched."); return(EINVAL); + } if (slt->irq) { ! if (((1 << slt->irq) & desc->irqmask)==0) { ! printf("crd: slot IRQ mismatched."); return(EINVAL); + } slt->irqref++; irq = slt->irq; } else { *************** *** 553,560 **** irq = pccard_alloc_intr(desc->irqmask, slot_irq_handler, (int)slt, drv->imask, slt->ctrl->imask); ! if (irq < 0) return(EINVAL); slt->irq = irq; slt->irqref = 1; slt->ctrl->mapirq(slt, slt->irq); --- 698,707 ---- irq = pccard_alloc_intr(desc->irqmask, slot_irq_handler, (int)slt, drv->imask, slt->ctrl->imask); ! if (irq < 0) { ! printf("crd: IRQ allocation failed."); return(EINVAL); + } slt->irq = irq; slt->irqref = 1; slt->ctrl->mapirq(slt, slt->irq); *************** *** 568,589 **** devi->running = 1; devi->drv = drv; devi->slt = slt; ! devi->isahd.id_irq = irq; devi->isahd.id_unit = desc->unit; devi->isahd.id_msize = desc->memsize; devi->isahd.id_iobase = desc->iobase; - bcopy(desc->misc, devi->misc, sizeof(desc->misc)); - if (irq) - devi->isahd.id_irq = 1 << irq; devi->isahd.id_flags = desc->flags; /* * Convert the memory to kernel space. */ if (desc->mem) ! devi->isahd.id_maddr = ! (caddr_t)(desc->mem + atdevbase - IOM_BEGIN); else ! devi->isahd.id_maddr = 0; devi->next = slt->devices; slt->devices = devi; s = splhigh(); --- 715,749 ---- devi->running = 1; devi->drv = drv; devi->slt = slt; ! #if 1 ! if (irq) ! devi->pd_irq = irq; ! else ! devi->pd_irq = 0; ! devi->pd_unit = desc->unit; ! devi->pd_msize = desc->memsize; ! devi->pd_iobase = desc->iobase; ! devi->pd_flags = desc->flags; ! ! /* compatible old driver */ ! if (irq) ! devi->isahd.id_irq = 1 << irq; ! else ! devi->isahd.id_irq = 0; devi->isahd.id_unit = desc->unit; devi->isahd.id_msize = desc->memsize; devi->isahd.id_iobase = desc->iobase; devi->isahd.id_flags = desc->flags; + #endif + bcopy(desc->misc, devi->misc, sizeof(desc->misc)); /* * Convert the memory to kernel space. */ if (desc->mem) ! devi->pd_maddr = (caddr_t)(desc->mem + atdevbase - IOM_BEGIN); else ! devi->pd_maddr = 0; ! devi->isahd.id_maddr = devi->pd_maddr; /* compatible old driver */ devi->next = slt->devices; slt->devices = devi; s = splhigh(); *************** *** 596,603 **** * the error. We assume that when we free the device, * it will also set 'running' to off. */ ! if (err) remove_device(devi); return(err); } --- 756,765 ---- * the error. We assume that when we free the device, * it will also set 'running' to off. */ ! if (err) { ! devi->running = 2; remove_device(devi); + } return(err); } *************** *** 643,656 **** * Enable 5V to the card so that the CIS can be read. */ slt->pwr.vcc = 50; ! slt->pwr.vpp = 0; /* * Disable any pending timeouts for this slot, and explicitly * power it off right now. Then, re-enable the power using * the (possibly new) power settings. */ ! untimeout(power_off_slot, (caddr_t)slt); ! power_off_slot(slt); slt->ctrl->power(slt); printf("Card inserted, slot %d\n", slt->slotnum); --- 805,823 ---- * Enable 5V to the card so that the CIS can be read. */ slt->pwr.vcc = 50; ! slt->pwr.vpp = 50; ! #if 0 ! #ifdef CB_TEST ! slt->ctrl->status(slt); ! #endif /* CB_TEST */ ! #endif /* * Disable any pending timeouts for this slot, and explicitly * power it off right now. Then, re-enable the power using * the (possibly new) power settings. */ ! untimeout(really_power_off_slot, (caddr_t)slt); ! really_power_off_slot(slt); slt->ctrl->power(slt); printf("Card inserted, slot %d\n", slt->slotnum); *************** *** 658,663 **** --- 825,836 ---- * Now start resetting the card. */ slt->ctrl->reset(slt); + #ifdef NECMG + /* + * slt->ctrl->reset(slt) is not return until reset is completed. + */ + necmg_pccard_enabler(slt); + #endif } /* *************** *** 678,684 **** * The slot and devices are disabled, but the * data structures are not unlinked. */ ! if (slt->state == filled) { int s = splhigh(); disable_slot(slt); slt->state = empty; --- 851,857 ---- * The slot and devices are disabled, but the * data structures are not unlinked. */ ! if (slt->state == filled || slt->state == inactive) { int s = splhigh(); disable_slot(slt); slt->state = empty; *************** *** 691,697 **** case card_inserted: slt->insert_seq = 1; timeout(inserted, (void *)slt, hz/4); ! pccard_remove_beep(); break; } } --- 864,870 ---- case card_inserted: slt->insert_seq = 1; timeout(inserted, (void *)slt, hz/4); ! pccard_insert_beep(); break; } } *************** *** 711,717 **** * caught, the handler returns true. */ for (devi = slt->devices; devi; devi = devi->next) ! if (devi->isahd.id_irq && devi->running && devi->drv->handler(devi)) return; /* --- 884,890 ---- * caught, the handler returns true. */ for (devi = slt->devices; devi; devi = devi->next) ! if (devi->pd_irq && devi->running && devi->drv->handler(devi)) return; /* *************** *** 775,781 **** oldmap = *mp; mp->flags = slt->rwmem|MDF_ACTIVE; #if 0 ! printf("Rd at offs %d, size %d\n", (int)uio->uio_offset, uio->uio_resid); #endif while (uio->uio_resid && error == 0) { --- 948,954 ---- oldmap = *mp; mp->flags = slt->rwmem|MDF_ACTIVE; #if 0 ! printf("Rd at win %d offs %d, size %d\n", win, (int)uio->uio_offset, uio->uio_resid); #endif while (uio->uio_resid && error == 0) { *************** *** 862,870 **** struct mem_desc *mp; struct io_desc *ip; int s, err; /* beep is disabled until the 1st call of crdioctl() */ ! pccard_beep_select(BEEP_ON); if (slt == 0 && cmd != PIOCRWMEM) return(ENXIO); --- 1035,1046 ---- struct mem_desc *mp; struct io_desc *ip; int s, err; + int pwval; /* beep is disabled until the 1st call of crdioctl() */ ! #if 0 ! pccard_beep_select(1); ! #endif if (slt == 0 && cmd != PIOCRWMEM) return(ENXIO); *************** *** 989,994 **** --- 1165,1223 ---- else pccard_failure_beep(); return err; + /* + * Virtual removal/insertion + * + * State of cards: + * + * insertion virtual removal + * (empty) --------> (filled) --------> (inactive) + * ^ ^ | ^ | | + * | | | | | | + * | +---------------+ +-----------------+ | + * | removal virtual insertion | + * | | + * +----------------------------------------+ + * removal + * + * -- hosokawa + */ + case PIOCSVIR: + pwval = *(int *)data; + /* virtual removal */ + if (!pwval) { + if (slt->state != filled) { + return EINVAL; + } + s = splhigh(); + disable_slot(slt); + slt->state = inactive; + splx(s); + pccard_remove_beep(); + #if 0 + timeout(enable_beep, (void *)NULL, hz/5); + #endif + selwakeup(&slt->selp); + } + /* virtual insertion */ + else { + if (slt->state != inactive) { + return EINVAL; + } + slt->insert_seq = 1; + timeout(inserted, (void *)slt, hz/4); + pccard_insert_beep(); + #if 0 + timeout(enable_beep, (void *)NULL, hz/5); + #endif + break; + } + break; + case PIOCSBEEP: + if (pccard_beep_select(*(int *)data)) { + return EINVAL; + } + break; } return(0); } *************** *** 1065,1067 **** --- 1294,1477 ---- } SYSINIT(crddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,crd_drvinit,NULL) + + #ifdef NECMG + #include + + int necmg_pccard_enabled = 0; + + int + necmg_pccard_enabler(struct slot *sp) + { + #define ENABLER_MEM 0xd0000 /* memory window(temporally use)*/ + #define ENABLER_UNIT 0 /* wdc0 primary IDE controller */ + #define ENABLER_IRQ 14 /* IRQ */ + #define ENABLER_IO_ADDR 0x1f0 /* I/O address */ + #define ENABLER_IO_SIZE 8 /* I/O length */ + + struct { + char *name; + int config_index; + int reset_time; + int io_flags; + } *conf = NULL, conf_table[] = { + { "SunDisk SDP", 2, 50*1000, IODF_WS | IODF_16BIT |IODF_CS16 }, + { "HITACHI FLASH", 2, 50*10000, IODF_WS | IODF_16BIT |IODF_CS16 }, + { "PCMCIA VFAC", 2, 50*1000, IODF_WS | IODF_16BIT |IODF_CS16 }, + + /* This line must be last one. */ + { "default", 2, 50*1000, IODF_WS | IODF_16BIT |IODF_CS16 } + }; + struct dev_desc dd; + int dev = sp->slotnum; + unsigned char tuple_code, tuple_len; + unsigned long config_reg = 0; + unsigned char func_id = 0; + unsigned char regmask; + char card_name[255]; + unsigned char *mem = (unsigned char *)(ENABLER_MEM + atdevbase - 0xA0000); + int i, j; + int s = splhigh(); + + sp->mem[0].window = 0; + sp->mem[0].flags = MDF_ATTR | MDF_ACTIVE; + sp->mem[0].start = (caddr_t)kvtop(mem); + sp->mem[0].size = PCCARD_MEMSIZE; + sp->mem[0].card = 0; + sp->ctrl->mapmem(sp, 0); + + card_name[0] = '\0'; + i = 0; + while (i < 1024*2) { + if ((tuple_code = mem[i]) == CIS_END) { + break; + } + if (tuple_code == CIS_NULL) { + i += 2; + continue; + } + tuple_len = mem[i + 2]; + + switch (tuple_code) { + case CIS_INFO_V1: + { + unsigned char *src = &mem[i+8], *dst = card_name; + while (*src != 0xff) { + *dst++ = *src ? *src : ' '; + src += 2; + } + *dst = '\0'; + } + break; + case CIS_CONF_MAP: + config_reg = mem[i + 10] * 256 + mem[i + 8]; + regmask = mem[i + 12]; + break; + case CIS_FUNC_ID: + func_id = mem[i + 4]; + break; + #ifdef NECMG_DEBUG + case CIS_CONFIG: + printf("CIS_CONFIG: "); + for (j = 0; j <= tuple_len; j++) { + printf("%02x ", mem[i + j*2]); + } + printf("\n"); + break; + #endif /* NECMG_DEBUG */ + } + i += 4 + tuple_len * 2; + } + for (i = 0; i < sizeof(conf_table)/sizeof(*conf_table); i++) { + if (bcmp(card_name, conf_table[i].name, strlen(conf_table[i].name)) == 0) { + conf = &conf_table[i]; + break; + } + } + if (conf == NULL) { + if (!necmg_pccard_enabled || func_id != 4) + printf("Unknown card, %s on slot %d.", card_name, sp->slotnum); + if (func_id == 4) { + /* ATA card function id */ + if (!necmg_pccard_enabled) + printf(" -- Try with default settings.\n"); + conf = &conf_table[sizeof(conf_table)/sizeof(*conf_table) - 1]; + } else { + printf(" function id = %d.\n", func_id); + printf("\n"); + splx(s); + return (0); + } + } + if (necmg_pccard_enabled) { + /* + printf("Already enabled, good bye.\n"); + return (0); + */ + } + /* + * config regster setup + */ + if (!necmg_pccard_enabled) + printf("pccard: enable %s on slot %d.\n", card_name, sp->slotnum); + + sp->mem[0].card = config_reg; + sp->ctrl->mapmem(sp, 0); + mem[config_reg % PCCARD_MEMSIZE] = 0x80; + DELAY(conf->reset_time); + mem[config_reg % PCCARD_MEMSIZE] = 0x00; + DELAY(conf->reset_time); + mem[config_reg % PCCARD_MEMSIZE] = (conf->config_index | 0x40); + DELAY(conf->reset_time); + if (regmask & 0x2) { + /*printf("Setting CCSR reg to 0x%x\n", 0);*/ + mem[config_reg % PCCARD_MEMSIZE + 4] = 0; + } + DELAY(4000); + + /* unmap attribute memory */ + sp->mem[0].flags = 0; + sp->ctrl->mapmem(sp, 0); + + /* + * assign mem + */ + /* no memory */ + + /* + * assign I/O + */ + sp->io[0].window = 0; + sp->io[0].flags = conf->io_flags | IODF_ACTIVE; + sp->io[0].start = ENABLER_IO_ADDR; + sp->io[0].size = ENABLER_IO_SIZE; + sp->ctrl->mapio(sp, 0); + + if (!necmg_pccard_enabled) { + /* + * assign driver + */ + strcpy(dd.name, "wdc"); + dd.unit = ENABLER_UNIT; + dd.irqmask = 1 << ENABLER_IRQ; + dd.flags = 0x80; + dd.mem = 0; + dd.memsize = 0; + dd.iobase = ENABLER_IO_ADDR; + + if (allocate_driver(sp, &dd) != 0) { + printf("driver allocation failed\n"); + } else { + necmg_pccard_enabled = 1; + wakeup(&necmg_pccard_enabled); + } + } else { + if (0 < sp->irqref) { + sp->ctrl->mapirq(sp, sp->irq); + } + } + + splx(s); + return (0); /* XXX */ + } + #endif /* NECMG */ Index: PAO/sys/pccard/pccard_beep.c diff -c PAO/sys/pccard/pccard_beep.c:1.1.1.1 PAO/sys/pccard/pccard_beep.c:1.1.1.1.6.1 *** PAO/sys/pccard/pccard_beep.c:1.1.1.1 Sun Apr 5 07:20:53 1998 --- PAO/sys/pccard/pccard_beep.c Sun Dec 6 07:49:36 1998 *************** *** 12,17 **** --- 12,22 ---- #include + #undef PCCARD_BEEP + #ifndef PCCARD_BEEP + #define PCCARD_BEEP 2 + #endif /* !PCCARD_BEEP */ + #define PCCARD_BEEP_PITCH0 1600 #define PCCARD_BEEP_DURATION0 20 #define PCCARD_BEEP_PITCH1 1200 *************** *** 19,24 **** --- 24,136 ---- #define PCCARD_BEEP_PITCH2 3200 #define PCCARD_BEEP_DURATION2 40 + static void pccard_insert_beep_type0(void) + { + /* dummy */ + } + + static void pccard_remove_beep_type0(void) + { + /* dummy */ + } + + static void pccard_success_beep_type0(void) + { + /* dummy */ + } + + static void pccard_failure_beep_type0(void) + { + /* dummy */ + } + + + static void pccard_insert_beep_type1(void) + { + sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0); + } + + static void pccard_remove_beep_type1(void) + { + sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0); + } + + static void pccard_success_beep_type1(void) + { + sysbeep(PCCARD_BEEP_PITCH1, PCCARD_BEEP_DURATION1); + } + + static void pccard_failure_beep_type1(void) + { + sysbeep(PCCARD_BEEP_PITCH2, PCCARD_BEEP_DURATION2); + } + + static void pccard_insert_beep0_type2(void *dummy) + { + sysbeep_cancel(); + sysbeep(1200, 5); + } + + static void pccard_insert_beep_type2(void) + { + sysbeep(1600, 20); + timeout(pccard_insert_beep0_type2, NULL, hz / 10); + } + + static void pccard_remove_beep0_type2(void *dummy) + { + sysbeep_cancel(); + sysbeep(1600, 5); + } + + static void pccard_remove_beep_type2(void) + { + sysbeep(1200, 20); + timeout(pccard_remove_beep0_type2, NULL, hz / 10); + } + + static void pccard_success_beep1_type2(void *dummy) + { + sysbeep_cancel(); + sysbeep(800, 15); + } + + static void pccard_success_beep0_type2(void *dummy) + { + sysbeep_cancel(); + sysbeep(1000, 20); + timeout(pccard_success_beep1_type2, NULL, hz / 15); + } + + static void pccard_success_beep_type2(void) + { + sysbeep(1200, 20); + timeout(pccard_success_beep0_type2, NULL, hz / 15); + } + + static void pccard_failure_beep1_type2(void *dummy) + { + sysbeep_cancel(); + sysbeep(2800, 15); + } + + static void pccard_failure_beep0_type2(void *dummy) + { + sysbeep_cancel(); + sysbeep(2400, 20); + timeout(pccard_failure_beep1_type2, NULL, hz / 15); + } + static void pccard_failure_beep_type2(void) + { + sysbeep(2000, 20); + timeout(pccard_failure_beep0_type2, NULL, hz / 15); + } + + static void (*insert)(void) = pccard_insert_beep_type0; + static void (*remove)(void) = pccard_remove_beep_type0; + static void (*success)(void) = pccard_success_beep_type0; + static void (*failure)(void) = pccard_failure_beep_type0; + static enum beepstate allow_beep = BEEP_OFF; /* *************** *** 33,38 **** --- 145,202 ---- allow_beep = 1; } + #ifdef PCCARD_BEEP + int pccard_beep_select(int type) + { + int errcode = 0; + + switch (type) { + case 0: + insert = pccard_insert_beep_type0; + remove = pccard_remove_beep_type0; + success = pccard_success_beep_type0; + failure = pccard_failure_beep_type0; + break; + case 1: + insert = pccard_insert_beep_type1; + remove = pccard_remove_beep_type1; + success = pccard_success_beep_type1; + failure = pccard_failure_beep_type1; + break; + case 2: + insert = pccard_insert_beep_type2; + remove = pccard_remove_beep_type2; + success = pccard_success_beep_type2; + failure = pccard_failure_beep_type2; + break; + default: + errcode = 1; + break; + } + return errcode; + } + + void pccard_insert_beep(void) + { + insert(); + } + + void pccard_remove_beep(void) + { + remove(); + } + + void pccard_success_beep(void) + { + success(); + } + + void pccard_failure_beep(void) + { + failure(); + } + + #else void pccard_insert_beep(void) { if (allow_beep == BEEP_ON) { *************** *** 65,67 **** --- 229,232 ---- { allow_beep = state; } + #endif /* PCCARD_BEEP */ Index: PAO/sys/pccard/pcic.c diff -c PAO/sys/pccard/pcic.c:1.1.1.3 PAO/sys/pccard/pcic.c:1.1.1.3.4.2 *** PAO/sys/pccard/pcic.c:1.1.1.3 Fri Jul 24 19:26:34 1998 --- PAO/sys/pccard/pcic.c Mon Dec 21 19:47:51 1998 *************** *** 30,38 **** /* * pcic98 : PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L. ! * by Noriyuki Hosobuchi */ #include #include #include --- 30,41 ---- /* * pcic98 : PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L. ! * by Noriyuki Hosobuchi . */ + #include "pcic.h" + #if NPCIC > 0 + #include #include #include *************** *** 43,64 **** #include #include ! #include #ifdef PC98 #include #endif - #include #include #include /* * Prototypes for interrupt handler. */ - static void pcicintr __P((int unit)); static int pcic_ioctl __P((struct slot *, int, caddr_t)); static int pcic_power __P((struct slot *)); static timeout_t pcic_reset; static void pcic_resume(struct slot *); static void pcic_disable __P((struct slot *)); static void pcic_mapirq __P((struct slot *, int)); --- 46,87 ---- #include #include ! #include #ifdef PC98 #include #endif #include #include #include + #include + /* + * TODO + * change driver.h -> pccardvar.h ?? + * (include struct pccard_device) + * (include struct pccard_devinfo) + * change slot.h -> pccardbus.h ?? + * (or merge to pccardvar.h) + */ + + #include "pci.h" + #if NPCI > 0 + #include + #include + #endif + + + #define CIRRUSHACK_FLAGS 0x1 /* * Prototypes for interrupt handler. */ static int pcic_ioctl __P((struct slot *, int, caddr_t)); static int pcic_power __P((struct slot *)); + #ifndef NECMG static timeout_t pcic_reset; + #else /* NECMG */ + static timeout_t necmg_pcic_reset; + #endif /* NECMG */ static void pcic_resume(struct slot *); static void pcic_disable __P((struct slot *)); static void pcic_mapirq __P((struct slot *, int)); *************** *** 68,95 **** #endif static int pcic_memory(struct slot *, int); static int pcic_io(struct slot *, int); ! static u_int build_freelist(u_int); /* * Per-slot data table. */ ! static struct pcic_slot { ! int slotnum; /* My slot number */ ! int index; /* Index register */ ! int data; /* Data register */ ! int offset; /* Offset value for index */ ! char controller; /* Device type */ ! char revision; /* Device Revision */ ! struct slot *slt; /* Back ptr to slot */ ! u_char (*getb)(struct pcic_slot *, int); ! void (*putb)(struct pcic_slot *, int, u_char); ! u_char *regs; /* Pointer to regs in mem */ ! } pcic_slots[PCIC_MAX_SLOTS]; ! static int pcic_irq; static unsigned pcic_imask; ! static struct slot_ctrl cinfo; /* * Internal inline functions for accessing the PCIC. --- 91,185 ---- #endif static int pcic_memory(struct slot *, int); static int pcic_io(struct slot *, int); ! #ifdef CB_TEST ! static void pcic_status __P((struct slot *)); ! static int cardbus_power __P((struct slot *)); ! static int cardbus_memory(struct slot *, int); ! static void cardbus_status __P((struct slot *)); ! #endif /* CB_TEST */ ! #ifdef PC98 ! /* local functions for PC98 Original PC-Card controller */ ! static int pcic98_power __P((struct slot *)); ! static void pcic98_mapirq __P((struct slot *, int)); ! static int pcic98_memory(struct slot *, int); ! static int pcic98_io(struct slot *, int); ! static timeout_t pcic98_reset; ! static void pcic98_disable __P((struct slot *)); ! static void pcic98_resume(struct slot *); ! #endif /*PC98*/ /* * Per-slot data table. */ ! static struct pcic_slot pcic_slots[MAXSLOT]; ! static int pcic_irq = 0; /*the control irq for pcic first seen*/ static unsigned pcic_imask; ! static struct slot_ctrl controller_info[NPCIC]; ! ! static int pcic_slotnum = 0; ! static int pcic_unit = 0; + #ifdef PC98 + static u_char pcic98_last_reg1; + #endif /*PC98*/ + + #include "isa.h" + #if NISA > 0 + static int pcic_isa_probe __P((struct isa_device *)); + static int pcic_isa_attach __P((struct isa_device *)); + struct isa_driver pcicdriver = { + pcic_isa_probe, pcic_isa_attach, "pcic", 0 + }; + + static int + pcic_isa_probe(isa_dev) + struct isa_device *isa_dev; + { + int ports, irq, i; + struct slot_ctrl *cinfo; + + /* isa_dev->id_unit check*/ + if (isa_dev->id_unit >= NPCIC) + return 0; + + /* initialize controller info */ + cinfo = &controller_info[isa_dev->id_unit]; + + /* used unit check*/ + if (cinfo->slot_use == 'u') { + /* already attached */ + return 0; + } + + /* isa_dev->id_irq is in "mask" style */ + irq = 0; + for (i = 0; i < 16; i++) { + if ((1 << i) & isa_dev->id_irq) { + irq = i; + break; + } + } + + ports = pcic_probe(cinfo, isa_dev->id_iobase, irq); + + return ports; + } + + static int + pcic_isa_attach(dev) + struct isa_device *dev; + { + int irq; + struct slot_ctrl *cinfo; + + cinfo = &controller_info[dev->id_unit]; + + pcic_attach(cinfo, dev->id_flags); + + return 1; /*XXX*/ + } + #endif /* NISA */ /* * Internal inline functions for accessing the PCIC. *************** *** 107,114 **** --- 197,231 ---- static __inline unsigned char getb2(struct pcic_slot *sp, int reg) { + return (sp->regs[reg + 0x800]); + } + + static __inline unsigned char + getb(struct pcic_slot *sp, int reg) + { + return sp->getb(sp, reg); + } + + #ifdef CB_TEST + static __inline unsigned char + cb_getb(struct pcic_slot *sp, int reg) + { return (sp->regs[reg]); } + + static __inline u_long + cb_getl(struct pcic_slot *sp, int reg) + { + u_long val = 0u; + + val |= sp->regs[reg+3] << 24; + val |= sp->regs[reg+2] << 16; + val |= sp->regs[reg+1] << 8; + val |= sp->regs[reg]; + + return val; + } + #endif /* CB_TEST */ /* * Write a register on the PCIC *************** *** 123,131 **** --- 240,271 ---- static __inline void putb2(struct pcic_slot *sp, int reg, unsigned char val) { + sp->regs[reg + 0x800] = val; + } + + static __inline void + putb(struct pcic_slot *sp, int reg, unsigned char val) + { + sp->putb(sp, reg, val); + } + + #ifdef CB_TEST + static __inline void + cb_putb(struct pcic_slot *sp, int reg, unsigned char val) + { sp->regs[reg] = val; } + static __inline void + cb_putl(struct pcic_slot *sp, int reg, u_long val) + { + sp->regs[reg] = val & 0xFF; + sp->regs[reg+1] = (val >> 8) & 0xFF; + sp->regs[reg+2] = (val >> 16) & 0xFF; + sp->regs[reg+3] = (val >> 24) & 0xFF; + } + #endif /* CB_TEST */ + /* * Clear bit(s) of a register. */ *************** *** 165,170 **** --- 305,326 ---- */ MOD_MISC(pcic); + #ifndef PCIC_INTR + #define PCIC_INTR (1 << PCIC_IRQ) + #endif + + #if NISA > 0 + static struct isa_device isa_devtab_pcic[] = { + { 0, &pcicdriver, IO_PCIC1, PCIC_INTR, -1, (caddr_t) 0, 0, pcicintr, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, + #ifndef PC98 + { 0, &pcicdriver, IO_PCIC3, PCIC_INTR, -1, (caddr_t) 0, 0, pcicintr, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, + { 0, &pcicdriver, IO_PCIC2, 0, -1, (caddr_t) 0, 0, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0 }, + { 0, &pcicdriver, IO_PCIC3, 0, -1, (caddr_t) 0, 0, NULL, 1, 0, 0, 0, 0, 0, 1, 0, 0 }, + #endif /*!PC98*/ + 0 + }; + #endif + /* * Module handler that processes loads and unloads. * Once the module is loaded, the probe routine *************** *** 174,179 **** --- 330,342 ---- pcic_handle(struct lkm_table *lkmtp, int cmd) { int err = 0; /* default = success*/ + int found = 0; + #if NISA > 0 + struct isa_device *dvp; + #endif + #if NPCI > 0 + extern struct pci_device pcic_pci_driver; + #endif switch(cmd) { case LKM_E_LOAD: *************** *** 183,193 **** */ if (lkmexists(lkmtp)) return(EEXIST); /* * Call the probe routine to find the slots. If * no slots exist, then don't bother loading the module. */ ! if (pcic_probe() == 0) return(ENODEV); break; /* Success*/ /* --- 346,376 ---- */ if (lkmexists(lkmtp)) return(EEXIST); + + bzero(pcic_slots, sizeof(pcic_slots)); + /* * Call the probe routine to find the slots. If * no slots exist, then don't bother loading the module. */ ! #if NPCI > 0 ! /* PCI PCIC probe */ ! if (pci_register_lkm (&pcic_pci_driver, 0) == 0) { ! #if 0 ! found++; ! #endif ! } ! #endif ! #if NISA > 0 ! /* ISA PCIC probe */ ! for (dvp = isa_devtab_pcic; dvp->id_driver; dvp++) ! if (pcic_isa_probe(dvp)) { ! pcic_isa_attach(dvp); ! found++; ! } ! #endif ! ! if (!found) return(ENODEV); break; /* Success*/ /* *************** *** 239,259 **** static int pcic_unload(struct lkm_table *lkmtp, int cmd) { ! int slot; struct pcic_slot *sp = pcic_slots; untimeout(pcictimeout, 0); ! if (pcic_irq) { ! for (slot = 0; slot < PCIC_MAX_SLOTS; slot++, sp++) { ! if (sp->slt) ! sp->putb(sp, PCIC_STAT_INT, 0); ! } ! unregister_intr(pcic_irq, pcicintr); } - pccard_remove_controller(&cinfo); return(0); } - #endif /* LKM */ #if 0 --- 422,445 ---- static int pcic_unload(struct lkm_table *lkmtp, int cmd) { ! int slot, unit; struct pcic_slot *sp = pcic_slots; untimeout(pcictimeout, 0); ! for (slot = 0; slot < MAXSLOT; slot++, sp++) { ! if (sp->slt) ! putb(sp, PCIC_STAT_INT, 0); ! if (sp->irq) ! unregister_intr(sp->irq, pcicintr); ! } ! for (unit = 0; unit < NPCIC; unit++) { ! struct slot_ctrl *cinfo = &controller_info[unit]; ! ! if (cinfo->slot_use == 'u') ! pccard_remove_controller(cinfo); } return(0); } #endif /* LKM */ #if 0 *************** *** 280,322 **** } #endif - static void - nullfunc(int unit) - { - /* empty */ - } - - static u_int - build_freelist(u_int pcic_mask) - { - int irq; - u_int mask, freemask; - - /* No free IRQs (yet). */ - freemask = 0; - - /* Walk through all of the IRQ's and find any that aren't allocated. */ - for (irq = 1; irq < ICU_LEN; irq++) { - /* - * If the PCIC controller can't generate it, don't - * bother checking to see if it it's free. - */ - mask = 1 << irq; - if (!(mask & pcic_mask)) continue; - - /* See if the IRQ is free. */ - if (register_intr(irq, 0, 0, nullfunc, NULL, irq) == 0) { - /* Give it back, but add it to the mask */ - INTRMASK(freemask, mask); - unregister_intr(irq, nullfunc); - } - } - #ifdef PCIC_DEBUG - printf("Freelist of IRQ's <0x%x>\n", freemask); - #endif - return freemask; - } - /* * entry point from main code to map/unmap memory context. */ --- 466,471 ---- *************** *** 325,374 **** { struct pcic_slot *sp = slt->cdata; struct mem_desc *mp = &slt->mem[win]; ! int reg = mp->window * PCIC_MEMSIZE + PCIC_MEMBASE; ! ! #ifdef PC98 ! if (sp->controller == PCIC_PC98) { ! if (mp->flags & MDF_ACTIVE) { ! /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */ ! unsigned char x; ! ! if ((unsigned long)mp->start != 0xda000) { ! printf("sys_addr must be 0xda000. requested address = 0x%x\n", ! mp->start); ! return(EINVAL); ! } ! ! /* omajinai ??? */ ! outb(PCIC98_REG0, 0); ! x = inb(PCIC98_REG1); ! x &= 0xfc; ! x |= 0x02; ! outb(PCIC98_REG1, x); ! ! outw(PCIC98_REG_PAGOFS, 0); ! ! if (mp->flags & MDF_ATTR) { ! outb(PCIC98_REG6, inb(PCIC98_REG6) | PCIC98_ATTRMEM); ! }else{ ! outb(PCIC98_REG6, inb(PCIC98_REG6) & (~PCIC98_ATTRMEM)); ! } ! ! outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN); ! ! #if 0 ! if (mp->flags & MDF_16BITS == 1) { /* 16bit */ ! outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_8BIT)); ! }else{ /* 8bit */ ! outb(PCIC98_REG2, inb(PCIC98_REG2) | PCIC98_8BIT); ! } ! #endif ! }else{ ! outb(PCIC98_REG_WINSEL, PCIC98_UNMAPWIN); ! } ! return 0; ! } ! #endif /* PC98 */ if (mp->flags & MDF_ACTIVE) { unsigned long sys_addr = (unsigned long)mp->start >> 12; --- 474,480 ---- { struct pcic_slot *sp = slt->cdata; struct mem_desc *mp = &slt->mem[win]; ! int reg = mp->window * PCIC_MEMSIZE + PCIC_MEMBASE0; if (mp->flags & MDF_ACTIVE) { unsigned long sys_addr = (unsigned long)mp->start >> 12; *************** *** 406,414 **** printf("Map window to sys addr 0x%x for %d bytes, card 0x%x\n", mp->start, mp->size, mp->card); printf("regs are: 0x%02x%02x 0x%02x%02x 0x%02x%02x flags 0x%x\n", ! sp->getb(sp, reg), sp->getb(sp, reg+1), ! sp->getb(sp, reg+2), sp->getb(sp, reg+3), ! sp->getb(sp, reg+4), sp->getb(sp, reg+5), mp->flags); #endif /* --- 512,520 ---- printf("Map window to sys addr 0x%x for %d bytes, card 0x%x\n", mp->start, mp->size, mp->card); printf("regs are: 0x%02x%02x 0x%02x%02x 0x%02x%02x flags 0x%x\n", ! getb(sp, reg), getb(sp, reg+1), ! getb(sp, reg+2), getb(sp, reg+3), ! getb(sp, reg+4), getb(sp, reg+5), mp->flags); #endif /* *************** *** 428,433 **** --- 534,547 ---- return(0); } + #ifdef CB_TEST + int + cardbus_memory(struct slot *slt, int win) + { + return(0); + } + #endif /* CB_TEST */ + /* * pcic_io - map or unmap I/O context */ *************** *** 437,482 **** int mask, reg; struct pcic_slot *sp = slt->cdata; struct io_desc *ip = &slt->io[win]; - #ifdef PC98 - if (sp->controller == PCIC_PC98) { - unsigned char x; - - #if 0 - if (win =! 0) { - printf("pcic98:Illegal PCIC I/O window request(%d)!", win); - return(EINVAL); - } - #endif - if (ip->flags & IODF_ACTIVE) { - unsigned short base; - - x = inb(PCIC98_REG2) & 0x0f; - if (! (ip->flags & IODF_16BIT)) - x |= PCIC98_8BIT; - - if (ip->size > 16) /* 128bytes mapping */ - x |= PCIC98_MAP128; - - x |= PCIC98_IOMEMORY; - outb(PCIC98_REG2, x); - - base = 0x80d0; - outw(PCIC98_REG4, base); /* 98side IO base */ - outw(PCIC98_REG5, ip->start); /* card side IO base */ - - #ifdef PCIC_DEBUG - printf("pcic98: IO mapped 0x%04x(98) -> 0x%04x(Card) and width %d bytes\n", - base, ip->start, ip->size); - #endif - ip->start = base; - - }else{ - outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_IOMEMORY)); - } - return 0; - } - #endif switch (win) { case 0: mask = PCIC_IO0_EN; --- 551,557 ---- *************** *** 511,524 **** * Flags for window 0 in lower nybble, and in upper nybble * for window 1. */ ! ioctlv = sp->getb(sp, PCIC_IOCTL); DELAY(100); switch (win) { case 0: ! sp->putb(sp, PCIC_IOCTL, x | (ioctlv & 0xf0)); break; case 1: ! sp->putb(sp, PCIC_IOCTL, (x << 4) | (ioctlv & 0xf)); break; } DELAY(100); --- 586,599 ---- * Flags for window 0 in lower nybble, and in upper nybble * for window 1. */ ! ioctlv = getb(sp, PCIC_IOCTL); DELAY(100); switch (win) { case 0: ! putb(sp, PCIC_IOCTL, x | (ioctlv & 0xf0)); break; case 1: ! putb(sp, PCIC_IOCTL, (x << 4) | (ioctlv & 0xf)); break; } DELAY(100); *************** *** 533,596 **** return(0); } /* * Look for an Intel PCIC (or compatible). * For each available slot, allocate a PC-CARD slot. */ - /* * VLSI 82C146 has incompatibilities about the I/O address * of slot 1. Assume it's the only PCIC whose vendor ID is 0x84, * contact Nate Williams if incorrect. */ int ! pcic_probe(void) { int slotnum, i, validslots = 0; - u_int free_irqs; - struct slot *slt; struct pcic_slot *sp; unsigned char c; ! static int maybe_vlsi = 0; - /* Determine the list of free interrupts */ - free_irqs = build_freelist(PCIC_INT_MASK_ALLOWED); - /* * Initialise controller information structure. */ ! cinfo.mapmem = pcic_memory; ! cinfo.mapio = pcic_io; ! cinfo.ioctl = pcic_ioctl; ! cinfo.power = pcic_power; ! cinfo.mapirq = pcic_mapirq; ! cinfo.reset = pcic_reset; ! cinfo.disable = pcic_disable; ! cinfo.resume = pcic_resume; ! cinfo.maxmem = PCIC_MEM_WIN; ! cinfo.maxio = PCIC_IO_WIN; ! cinfo.irqs = free_irqs; ! cinfo.imask = &pcic_imask; ! ! #ifdef LKM ! bzero(pcic_slots, sizeof(pcic_slots)); ! #endif ! sp = pcic_slots; ! for (slotnum = 0; slotnum < PCIC_MAX_SLOTS; slotnum++, sp++) { /* * Initialise the PCIC slot table. */ ! sp->getb = getb1; ! sp->putb = putb1; ! if (slotnum < 4) { ! sp->index = PCIC_INDEX_0; ! sp->data = PCIC_DATA_0; ! sp->offset = slotnum * PCIC_SLOT_SIZE; } else { ! sp->index = PCIC_INDEX_1; ! sp->data = PCIC_DATA_1; ! sp->offset = (slotnum - 4) * PCIC_SLOT_SIZE; } /* * XXX - Screwed up slot 1 on the VLSI chips. According to * the Linux PCMCIA code from David Hinds, working chipsets --- 608,743 ---- return(0); } + #ifdef CB_TEST + extern struct cb_slot *get_cb_info(u_long iobase); + extern int get_pci_pcic_slots(u_long iobase); + #endif /* CB_TEST */ + #if NPCI > 0 + extern int get_pci_pcic_info(u_long iobase, pcici_t *tag); + extern char set_controller_info(pcici_t tag, struct slot_ctrl *cinfo); + #endif /* NPCI */ + /* * Look for an Intel PCIC (or compatible). * For each available slot, allocate a PC-CARD slot. */ /* * VLSI 82C146 has incompatibilities about the I/O address * of slot 1. Assume it's the only PCIC whose vendor ID is 0x84, * contact Nate Williams if incorrect. + * rewrite: NAKAGAWA, Yoshihisa + */ + /* + * TODO: + * separate pcic_probe() and initialize + * merge pcic_probe() to pcic_isa_probe() */ int ! pcic_probe(struct slot_ctrl *cinfo, int iobase, int irq) { int slotnum, i, validslots = 0; struct pcic_slot *sp; unsigned char c; ! int maybe_vlsi = 0; ! int iorange = 0; ! char oc = 0; ! int max_slots = pcic_slotnum > MAXSLOT - PCIC_MAX_SLOTS ? ! MAXSLOT - pcic_slotnum : PCIC_MAX_SLOTS; ! #if NPCI > 0 ! pcici_t tag; ! char pci_controller = -1; ! #endif /* NPCI */ ! #ifdef CB_TEST ! int pci_slots; ! ! pci_slots = get_pci_pcic_slots(iobase); ! if (pci_slots) max_slots = pci_slots; ! #endif /* CB_TEST */ ! ! /* try to share slot irq */ ! if (irq == 0 && pcic_irq) { ! printf("pcic%d: sharing irq %d with other pcic\n", ! pcic_unit, pcic_irq); ! irq = pcic_irq; ! } /* * Initialise controller information structure. */ ! cinfo->mapmem = pcic_memory; ! cinfo->mapio = pcic_io; ! #ifdef CB_TEST ! cinfo->status = pcic_status; ! #endif /* CB_TEST */ ! cinfo->ioctl = pcic_ioctl; ! cinfo->power = pcic_power; ! cinfo->mapirq = pcic_mapirq; ! #ifndef NECMG ! cinfo->reset = pcic_reset; ! #else /* NECMG */ ! cinfo->reset = necmg_pcic_reset; ! #endif /* NECMG */ ! cinfo->disable = pcic_disable; ! cinfo->resume = pcic_resume; ! cinfo->maxmem = PCIC_MEM_WIN; ! cinfo->maxio = PCIC_IO_WIN; ! cinfo->irqs = 0; /* set pccard.c */ ! cinfo->imask = &pcic_imask; /* XXXX pccard.c ? */ ! cinfo->slots = 0; ! cinfo->name = "Unknown!"; ! #ifdef CB_TEST ! cinfo->cardbus = 0; ! #endif /* CB_TEST */ ! cinfo->next = NULL; ! ! id_recheck: ! sp = &pcic_slots[pcic_slotnum]; ! for (slotnum = 0; slotnum < max_slots; slotnum++, sp++) { /* * Initialise the PCIC slot table. */ ! #if NPCI > 0 ! if (get_pci_pcic_info(iobase, &tag)) { ! /* override controller info */ ! pci_controller = set_controller_info(tag, cinfo); ! } ! #endif /* NPCI */ ! #ifdef CB_TEST ! if (!cinfo->cardbus) { ! #endif /* CB_TEST */ ! sp->getb = getb1; ! sp->putb = putb1; ! sp->index = iobase; ! sp->data = iobase + 1; ! sp->regs = 0; ! #ifdef CB_TEST } else { ! struct cb_slot *cb_info; ! ! cb_info = get_cb_info(iobase); ! if (cb_info) { ! cb_info += slotnum; ! sp->regs = (u_char *)cb_info->cb_base; ! } ! sp->getb = getb2; ! sp->putb = putb2; ! sp->index = 0; ! sp->data = 0; ! #if 0 ! sp->regs = (u_char *)iobase; ! max_slots = 1; ! #endif } + #endif /* CB_TEST */ + iorange = iorange < 2 ? 2 : iorange; + sp->offset = slotnum * PCIC_SLOT_SIZE; + sp->irq = irq; + + #ifdef CB_TEST + if (pci_controller >= 0) { + sp->controller = pci_controller; + } else { + #endif /* CB_TEST */ /* * XXX - Screwed up slot 1 on the VLSI chips. According to * the Linux PCMCIA code from David Hinds, working chipsets *************** *** 598,614 **** * ones would need to be probed at the new offset we set after * we assume it's broken. */ ! if (slotnum == 1 && maybe_vlsi && sp->getb(sp, PCIC_ID_REV) != 0x84) { sp->index += 4; sp->data += 4; sp->offset = PCIC_SLOT_SIZE << 1; } /* * see if there's a PCMCIA controller here * Intel PCMCIA controllers use 0x82 and 0x83 * IBM clone chips use 0x88 and 0x89, apparently */ ! c = sp->getb(sp, PCIC_ID_REV); sp->revision = -1; switch(c) { /* --- 745,764 ---- * ones would need to be probed at the new offset we set after * we assume it's broken. */ ! if (maybe_vlsi && slotnum == 1) { sp->index += 4; sp->data += 4; sp->offset = PCIC_SLOT_SIZE << 1; + iorange = iorange < 6 ? 6 : iorange; } /* * see if there's a PCMCIA controller here * Intel PCMCIA controllers use 0x82 and 0x83 * IBM clone chips use 0x88 and 0x89, apparently */ ! c = getb(sp, PCIC_ID_REV); ! if (bootverbose) ! printf("PCIC ID = 0x%02x\n", (u_int)c); sp->revision = -1; switch(c) { /* *************** *** 624,630 **** outb(sp->index, 0x0E); outb(sp->index, 0x37); setb(sp, 0x3A, 0x40); ! c = sp->getb(sp, PCIC_ID_REV); if (c & 0x08) { sp->controller = ((sp->revision = c & 7) == 4) ? PCIC_VG469 : PCIC_VG468 ; --- 774,780 ---- outb(sp->index, 0x0E); outb(sp->index, 0x37); setb(sp, 0x3A, 0x40); ! c = getb(sp, PCIC_ID_REV); if (c & 0x08) { sp->controller = ((sp->revision = c & 7) == 4) ? PCIC_VG469 : PCIC_VG468 ; *************** *** 634,651 **** /* * Check for RICOH RF5C396 PCMCIA Controller */ ! c = sp->getb(sp, 0x3a); if (c == 0xb2) { sp->controller = PCIC_RF5C396; } break; /* ! * VLSI chips. */ case 0x84: ! sp->controller = PCIC_VLSI; ! maybe_vlsi = 1; break; case 0x88: case 0x89: --- 784,804 ---- /* * Check for RICOH RF5C396 PCMCIA Controller */ ! c = getb(sp, 0x3a); if (c == 0xb2) { sp->controller = PCIC_RF5C396; } break; /* ! * 82365DF or clones or VLSI. */ case 0x84: ! if (!maybe_vlsi) { ! sp->controller = PCIC_I82365DF; ! } else { ! sp->controller = PCIC_VLSI; ! } break; case 0x88: case 0x89: *************** *** 654,671 **** break; case 0x8a: sp->controller = PCIC_IBM_KING; - sp->revision = c & 1; break; default: continue; } /* * Check for Cirrus logic chips. */ ! sp->putb(sp, 0x1F, 0); ! c = sp->getb(sp, 0x1F); if ((c & 0xC0) == 0xC0) { ! c = sp->getb(sp, 0x1F); if ((c & 0xC0) == 0) { if (c & 0x20) sp->controller = PCIC_PD672X; --- 807,834 ---- break; case 0x8a: sp->controller = PCIC_IBM_KING; break; default: + /* + * check VLSI chips. + */ + if (slotnum == 1 && oc == PCIC_I82365DF) { + maybe_vlsi = 1; + validslots = 0; + goto id_recheck; + } continue; } + /* store old controller type */ + oc = sp->controller; + /* * Check for Cirrus logic chips. */ ! putb(sp, 0x1F, 0); ! c = getb(sp, 0x1F); if ((c & 0xC0) == 0xC0) { ! c = getb(sp, 0x1F); if ((c & 0xC0) == 0) { if (c & 0x20) sp->controller = PCIC_PD672X; *************** *** 674,720 **** sp->revision = 8 - ((c & 0x1F) >> 2); } } switch(sp->controller) { case PCIC_I82365: ! cinfo.name = "Intel 82365"; break; case PCIC_IBM: ! cinfo.name = "IBM PCIC"; break; case PCIC_IBM_KING: ! cinfo.name = "IBM KING PCMCIA Controller"; break; case PCIC_PD672X: ! cinfo.name = "Cirrus Logic PD672X"; break; case PCIC_PD6710: ! cinfo.name = "Cirrus Logic PD6710"; break; case PCIC_VG468: ! cinfo.name = "Vadem 468"; break; case PCIC_VG469: ! cinfo.name = "Vadem 469"; break; case PCIC_RF5C396: ! cinfo.name = "Ricoh RF5C396"; break; case PCIC_VLSI: ! cinfo.name = "VLSI 82C146"; break; default: ! cinfo.name = "Unknown!"; break; } /* * OK it seems we have a PCIC or lookalike. * Allocate a slot and initialise the data structures. */ - validslots++; sp->slotnum = slotnum; ! slt = pccard_alloc_slot(&cinfo); if (slt == 0) continue; slt->cdata = sp; sp->slt = slt; /* --- 837,998 ---- sp->revision = 8 - ((c & 0x1F) >> 2); } } + #if NPCI > 0 + if (pci_controller >= 0) { + sp->controller = pci_controller; + } else { + #endif /* NPCI */ switch(sp->controller) { case PCIC_I82365: ! cinfo->name = "Intel 82365A/B"; ! break; ! case PCIC_I82365DF: ! cinfo->name = "Intel 82365DF"; break; case PCIC_IBM: ! cinfo->name = "IBM PCIC"; break; case PCIC_IBM_KING: ! cinfo->name = "IBM KING PCMCIA Controller"; break; case PCIC_PD672X: ! cinfo->name = "Cirrus Logic PD672X"; break; case PCIC_PD6710: ! cinfo->name = "Cirrus Logic PD6710"; break; case PCIC_VG468: ! cinfo->name = "Vadem 468"; break; case PCIC_VG469: ! cinfo->name = "Vadem 469"; break; case PCIC_RF5C396: ! cinfo->name = "Ricoh RF5C396"; break; case PCIC_VLSI: ! cinfo->name = "VLSI 82C146"; break; default: ! cinfo->name = "Unknown!"; break; } + #if NPCI > 0 + } + #endif /* NPCI */ + #ifdef CB_TEST + } + #endif /* CB_TEST */ + validslots++; + } + #ifdef PC98 + if (validslots == 0) { + sp = &pcic_slots[pcic_slotnum]; + if (inb(PCIC98_REG0) != 0xff) { + sp->controller = PCIC_PC98; + sp->revision = 0; + cinfo->mapmem = pcic98_memory; + cinfo->mapio = pcic98_io; + cinfo->power = pcic98_power; + cinfo->mapirq = pcic98_mapirq; + cinfo->reset = pcic98_reset; + cinfo->disable = pcic98_disable; + cinfo->resume = pcic98_resume; + cinfo->name = "PC98 Original"; + cinfo->maxmem = 1; + #if 0 + cinfo->maxio = 1; + #else + cinfo->maxio = 2; /* fake for UE2212 LAN card */ + #endif + validslots++; + } + } + #endif /* PC98 */ + cinfo->slots = validslots; + + return validslots ? iorange : 0; + } + + /* + * This code is for a PC which the ExCA timing register isn't + * defined by BIOS. When you use this, it is necessary to write + * "flags 0x1" in a line of pcic? in kernel configuration file. + * Takeshi Shibagaki(shiba@jp.freebsd.org) + */ + static void + cirrus_hack(struct pcic_slot *sp) + { + switch (sp->controller) { + case PCIC_PD6710: + case PCIC_PD672X: + sp->putb(sp, PCIC_TIME_SETUP0, 0x01); + sp->putb(sp, PCIC_TIME_CMD0, 0x06); + sp->putb(sp, PCIC_TIME_RECOV0, 0x03); + sp->putb(sp, PCIC_TIME_SETUP1, 0x01); + sp->putb(sp, PCIC_TIME_CMD1, 0x0f); + sp->putb(sp, PCIC_TIME_RECOV1, 0x03); + break; + case PCIC_PD6729: + sp->putb(sp, PCIC_TIME_SETUP0, 0x01); + sp->putb(sp, PCIC_TIME_CMD0, 0x05); + sp->putb(sp, PCIC_TIME_RECOV0, 0x00); + sp->putb(sp, PCIC_TIME_SETUP1, 0x01); + sp->putb(sp, PCIC_TIME_CMD1, 0x14); + sp->putb(sp, PCIC_TIME_RECOV1, 0x00); + break; + case PCIC_PD6832: + sp->putb(sp, PCIC_TIME_SETUP0, 0x00); + sp->putb(sp, PCIC_TIME_CMD0, 0x07); + sp->putb(sp, PCIC_TIME_RECOV0, 0x04); + sp->putb(sp, PCIC_TIME_SETUP1, 0x03); + sp->putb(sp, PCIC_TIME_CMD1, 0x1d); + sp->putb(sp, PCIC_TIME_RECOV1, 0x04); + break; + } + /* + * This code is to turn on speaker enable bit in + * the ExCA register. + * In fact, the bit must be defined by BIOS. + * I don't know a reason that the Low-Power Dynamic Mode + * enable bit turn on to '1'. + * Please justify, someone. + * Takeshi Shibagaki(shiba@jp.freebsd.org) + */ + switch (sp->controller) { + case PCIC_PD6710: + case PCIC_PD672X: + case PCIC_PD6729: + setb(sp, CL672X_PCIC_MISC2, CL672X_M2_LPDM_EN); + case PCIC_PD6832: + setb(sp, CL672X_PCIC_MISC1, CL672X_M1_SPKR_EN); + break; + } + } + + int + pcic_attach(struct slot_ctrl *cinfo, int flags) + { + int slotnum, i; + struct slot *slt; + struct pcic_slot *sp; + #ifdef CB_TEST + struct cb_slot *cb_info; + #endif /* CB_TEST */ + + pccard_add_controller(cinfo); + sp = &pcic_slots[pcic_slotnum]; + for (slotnum = 0; slotnum < cinfo->slots; slotnum++, sp++) { /* * OK it seems we have a PCIC or lookalike. * Allocate a slot and initialise the data structures. */ sp->slotnum = slotnum; ! slt = pccard_alloc_slot(cinfo); if (slt == 0) continue; + printf("pcic%d: slot %d controller I/O address 0x%x\n", + pcic_unit, slotnum, sp->index); slt->cdata = sp; sp->slt = slt; /* *************** *** 723,751 **** */ if (pcic_irq == 0) { pcic_imask = SWI_MASK; ! pcic_irq = pccard_alloc_intr(free_irqs, ! pcicintr, 0, &pcic_imask, NULL); ! if (pcic_irq < 0) ! printf("pcic: failed to allocate IRQ\n"); ! else ! printf("pcic: controller irq %d\n", pcic_irq); ! } ! /* ! * Modem cards send the speaker audio (dialing noises) ! * to the host's speaker. Cirrus Logic PCIC chips must ! * enable this. There is also a Low Power Dynamic Mode bit ! * that claims to reduce power consumption by 30%, so ! * enable it and hope for the best. ! */ ! if (sp->controller == PCIC_PD672X) { ! setb(sp, PCIC_MISC1, PCIC_SPKR_EN); ! setb(sp, PCIC_MISC2, PCIC_LPDM_EN); } /* * Check for a card in this slot. */ setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST); ! if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) != PCIC_CD) { slt->laststate = slt->state = empty; } else { slt->laststate = slt->state = filled; --- 1001,1031 ---- */ if (pcic_irq == 0) { pcic_imask = SWI_MASK; ! if (sp->irq) ! pcic_irq = sp->irq; ! else { ! printf( ! "pcic%d: no irq specified, no previous pcic irq found\n", pcic_unit); ! } } + /* * Check for a card in this slot. */ + #ifdef PC98 + if(sp->controller == PCIC_PC98) { + pcic98_last_reg1 = inb(PCIC98_REG1); + if (pcic98_last_reg1 & PCIC98_CARDEXIST) { + /* PCMCIA card exist */ + slt->laststate = slt->state = filled; + pccard_event(sp->slt, card_inserted); + } else { + slt->laststate = slt->state = empty; + } + } else { + #endif /*PC98*/ setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST); ! if ((getb(sp, PCIC_STATUS) & PCIC_CD) != PCIC_CD) { slt->laststate = slt->state = empty; } else { slt->laststate = slt->state = filled; *************** *** 754,800 **** /* * Assign IRQ for slot changes */ ! if (pcic_irq > 0) ! sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); ! } #ifdef PC98 - if (validslots == 0) { - sp = pcic_slots; - slotnum = 0; - if (inb(PCIC98_REG0) != 0xff) { - sp->controller = PCIC_PC98; - sp->revision = 0; - cinfo.name = "PC98 Original"; - cinfo.maxmem = 1; - cinfo.maxio = 1; - /* cinfo.irqs = PCIC_INT_MASK_ALLOWED;*/ - cinfo.irqs = 0x1468; - validslots++; - sp->slotnum = slotnum; - - slt = pccard_alloc_slot(&cinfo); - if (slt == 0) { - printf("pcic98: slt == NULL\n"); - goto pcic98_probe_end; - } - slt->cdata = sp; - sp->slt = slt; - - /* Check for a card in this slot */ - if (inb(PCIC98_REG1) & PCIC98_CARDEXIST) { - /* PCMCIA card exist */ - slt->laststate = slt->state = filled; - pccard_event(sp->slt, card_inserted); - } else { - slt->laststate = slt->state = empty; } ! } ! pcic98_probe_end: } ! #endif /* PC98 */ ! if (validslots) timeout(pcictimeout, 0, hz/2); ! return(validslots); } /* --- 1034,1060 ---- /* * Assign IRQ for slot changes */ ! if (sp->irq > 0) ! putb(sp, PCIC_STAT_INT, (sp->irq << 4) | 0xF); ! /* ! * If flags 0x1 is defined in kernel configuration file, ! * jump to cirrus pcic specific code. ! */ ! if((flags & CIRRUSHACK_FLAGS) == CIRRUSHACK_FLAGS) ! cirrus_hack(sp); #ifdef PC98 } ! #endif /*PC98*/ } ! if (cinfo->slots) { timeout(pcictimeout, 0, hz/2); ! cinfo->slot_use = 'u'; ! } ! ! pcic_slotnum += cinfo->slots; ! pcic_unit++; ! ! return 1; } /* *************** *** 813,828 **** */ case PIOCGREG: ((struct pcic_reg *)data)->value = ! sp->getb(sp, ((struct pcic_reg *)data)->reg); break; case PIOCSREG: ! sp->putb(sp, ((struct pcic_reg *)data)->reg, ((struct pcic_reg *)data)->value); break; } return(0); } /* * pcic_power - Enable the power of the slot according to * the parameters in the power structure(s). --- 1073,1157 ---- */ case PIOCGREG: ((struct pcic_reg *)data)->value = ! getb(sp, ((struct pcic_reg *)data)->reg); break; case PIOCSREG: ! putb(sp, ((struct pcic_reg *)data)->reg, ((struct pcic_reg *)data)->value); break; } return(0); } + #ifdef CB_TEST + /* + * pcic_status - Get slot status + */ + static void + pcic_status(struct slot *slt) + { + struct pcic_slot *sp = slt->cdata; + unsigned char reg; + int stschg = 0, detect = 0, power = 0; + int ready = 0; + + reg = getb(sp, PCIC_STATUS); + if ((reg & PCIC_CD) == PCIC_CD) + detect = 1; + if (reg & PCIC_POW) + power = 1; + if (reg & PCIC_READY) + ready = 1; + + if (sp->controller == PCIC_PD672X) { + reg = getb (sp, CL672X_PCIC_MISC1); + if (!(reg & CL672X_M1_5V_DET)) + slt->pwr.vcc = 33; + } + if (sp->controller == PCIC_VG469) { + reg = getb (sp, VG469_VSENSE); + if (slt->ctrl->slots & 1) { + if (!(reg & VG469_VSENSE_B_VS1)) + slt->pwr.vcc = 33; + } else { + if (!(reg & VG469_VSENSE_A_VS1)) + slt->pwr.vcc = 33; + } + } + + return; + } + + void + cardbus_status(struct slot *slt) + { + struct pcic_slot *sp = slt->cdata; + u_long reg; + int stschg = 0, detect = 0, power = 0, cardbus = 0; + int ready = 0; + + if (slt->ctrl->cardbus) { + reg = cb_getl(sp, CB_PRESENT_STATE); + if (reg & CB_CSTSCHG) + stschg = 1; + if (!(reg & CB_CCD1) && !(reg & CB_CCD2)) + detect = 1; + if (reg & CB_POWER_CYCLE) { + power = 1; + ready = 1; + } + if (reg & CB_CB_CARD) + cardbus = 1; + if (reg & CB_5V_CARD) + slt->pwr.vcc = 50; + if (reg & CB_3V_CARD) + slt->pwr.vcc = 33; + } + + return; + } + #endif /* CB_TEST */ + /* * pcic_power - Enable the power of the slot according to * the parameters in the power structure(s). *************** *** 834,868 **** struct pcic_slot *sp = slt->cdata; switch(sp->controller) { ! #ifdef PC98 ! case PCIC_PC98: ! reg = inb(PCIC98_REG6) & (~PCIC98_VPP12V); ! switch(slt->pwr.vpp) { ! default: ! return(EINVAL); ! case 50: ! break; ! case 120: ! reg |= PCIC98_VPP12V; ! break; ! } ! outb(PCIC98_REG6, reg); ! DELAY(100*1000); ! ! reg = inb(PCIC98_REG2) & (~PCIC98_VCC3P3V); ! switch(slt->pwr.vcc) { ! default: ! return(EINVAL); ! case 33: ! reg |= PCIC98_VCC3P3V; ! break; ! case 50: ! break; ! } ! outb(PCIC98_REG2, reg); ! DELAY(100*1000); ! return (0); ! #endif case PCIC_PD672X: case PCIC_PD6710: case PCIC_VG468: --- 1163,1170 ---- struct pcic_slot *sp = slt->cdata; switch(sp->controller) { ! case PCIC_PD6832: ! case PCIC_PD6729: case PCIC_PD672X: case PCIC_PD6710: case PCIC_VG468: *************** *** 870,875 **** --- 1172,1183 ---- case PCIC_RF5C396: case PCIC_VLSI: case PCIC_IBM_KING: + case PCIC_I82365DF: + case PCIC_TI1130: + case PCIC_TI1131: + case PCIC_TI1220: + case PCIC_TI1221: + case PCIC_TI1250: switch(slt->pwr.vpp) { default: return(EINVAL); *************** *** 898,931 **** (sp->controller == PCIC_VG469)) setb(sp, 0x2f, 0x03) ; else ! setb(sp, 0x16, 0x02); break; case 50: ! if (sp->controller == PCIC_IBM_KING) { ! reg |= PCIC_VCC_5V_KING; ! break; ! } reg |= PCIC_VCC_5V; if ((sp->controller == PCIC_VG468)|| (sp->controller == PCIC_VG469)) clrb(sp, 0x2f, 0x03) ; else ! clrb(sp, 0x16, 0x02); break; } break; } ! sp->putb(sp, PCIC_POWER, reg); DELAY(300*1000); if (slt->pwr.vcc) { reg |= PCIC_OUTENA; ! sp->putb(sp, PCIC_POWER, reg); DELAY(100*1000); } /* Some chips are smarter than us it seems, so if we weren't * allowed to use 5V, try 3.3 instead */ ! if (!(sp->getb(sp, PCIC_STATUS) & 0x40) && slt->pwr.vcc == 50) { slt->pwr.vcc = 33; slt->pwr.vpp = 0; return (pcic_power(slt)); --- 1206,1239 ---- (sp->controller == PCIC_VG469)) setb(sp, 0x2f, 0x03) ; else ! setb(sp, PCIC_CDGC, 0x02); break; case 50: ! if (sp->controller == PCIC_IBM_KING) { ! reg |= PCIC_VCC_5V_KING; ! break; ! } reg |= PCIC_VCC_5V; if ((sp->controller == PCIC_VG468)|| (sp->controller == PCIC_VG469)) clrb(sp, 0x2f, 0x03) ; else ! clrb(sp, PCIC_CDGC, 0x02); break; } break; } ! putb(sp, PCIC_POWER, reg); DELAY(300*1000); if (slt->pwr.vcc) { reg |= PCIC_OUTENA; ! putb(sp, PCIC_POWER, reg); DELAY(100*1000); } /* Some chips are smarter than us it seems, so if we weren't * allowed to use 5V, try 3.3 instead */ ! if (!(getb(sp, PCIC_STATUS) & 0x40) && slt->pwr.vcc == 50) { slt->pwr.vcc = 33; slt->pwr.vpp = 0; return (pcic_power(slt)); *************** *** 933,938 **** --- 1241,1307 ---- return(0); } + #ifdef CB_TEST + int + cardbus_power(struct slot *slt) + { + u_long reg = 0u; + struct pcic_slot *sp = slt->cdata; + struct slot_ctrl *cinfo = slt->ctrl; + u_int16_t brgcntl; + + if (slt->ctrl->cardbus) { + switch(slt->pwr.vpp) { + default: + return(EINVAL); + case 0: + break; + case 50: + reg |= CB_VPP_5V; + break; + case 33: + reg |= CB_VPP_3V; + break; + case 120: + reg |= CB_VPP_12V; + break; + } + switch(slt->pwr.vcc) { + default: + return(EINVAL); + case 0: + break; + case 50: + reg |= CB_VCC_5V; + break; + case 33: + reg |= CB_VCC_3V; + break; + } + if (reg != cb_getl(sp, CB_CONTROL)) { + cb_putl(sp, CB_CONTROL, reg); + DELAY(100*1000); + } + + /* Bridge Control */ + #if 0 /* XXXX */ + brgcntl = pci_cfgread(cinfo->tag, CB_PCI_BRIDGE_CTRL, 2); + brgcntl &= ~CB_BCR_CB_RESET; + pci_cfgwrite(cinfo->tag, CB_PCI_BRIDGE_CTRL, brgcntl, 2); + #endif + + #if 1 + reg = cb_getl(sp, CB_PRESENT_STATE); + if (reg & CB_POWER_CYCLE) + printf("powered up\n"); + else + printf("not yet powered up\n"); + #endif + } + return(0); + } + #endif /* CB_TEST */ + /* * tell the PCIC which irq we want to use. only the following are legal: * 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 *************** *** 941,981 **** pcic_mapirq(struct slot *slt, int irq) { struct pcic_slot *sp = slt->cdata; ! #ifdef PC98 ! if (sp->controller == PCIC_PC98) { ! unsigned char x; ! switch (irq) { ! case 3: ! x = PCIC98_INT0; break; ! case 5: ! x = PCIC98_INT1; break; ! case 6: ! x = PCIC98_INT2; break; ! case 10: ! x = PCIC98_INT4; break; ! case 12: ! x = PCIC98_INT5; break; ! case 0: /* disable */ ! x = PCIC98_INTDISABLE; ! break; ! default: ! printf("pcic98: illegal irq %d\n", irq); ! return; ! } ! #ifdef PCIC_DEBUG ! printf("pcic98: irq=%d mapped.\n", irq); ! #endif ! outb(PCIC98_REG3, x); - return; - } - #endif if (irq == 0) clrb(sp, PCIC_INT_GEN, 0xF); else ! sp->putb(sp, PCIC_INT_GEN, ! (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); } /* * pcic_reset - Reset the card and enable initial power. --- 1310,1371 ---- pcic_mapirq(struct slot *slt, int irq) { struct pcic_slot *sp = slt->cdata; ! u_char x; if (irq == 0) clrb(sp, PCIC_INT_GEN, 0xF); else ! putb(sp, PCIC_INT_GEN, ! (getb(sp, PCIC_INT_GEN) & 0xF0) | irq); ! #if NPCI > 0 ! switch (sp->controller) { ! /* CLPD-6832 ISA-mode interrupt support (experimental) */ ! case PCIC_PD6832: ! /* Read "Misc Control 3" register of PD-6832 */ ! putb(sp, CL6832_ExCA_EXTEND_INDEX, CL6832_ExCA_EXT_MISC3); ! x = getb(sp, CL6832_ExCA_EXTEND_DATA); ! #if 1 ! printf("Experimental clpd-6832 support:\n"); ! printf("please send the following messages to hosokawa@jp.FreeBSD.org\n"); ! printf("Misc 3 register is 0x%x\n", (u_int)x); ! #endif ! x = ((x & ~0x3) | 0x1); /* set "external hardware" bit */ ! #if 1 ! printf("Set Misc 3 register to 0x%x\n", (u_int)x); ! #endif ! putb(sp, CL6832_ExCA_EXTEND_INDEX, CL6832_ExCA_EXT_MISC3); ! putb(sp, CL6832_ExCA_EXTEND_DATA, x); ! ! /* check it again */ ! putb(sp, CL6832_ExCA_EXTEND_INDEX, CL6832_ExCA_EXT_MISC3); ! x = getb(sp, CL6832_ExCA_EXTEND_DATA); ! #if 1 ! printf("Misc 3 register is 0x%x\n", (u_int)x); ! #endif ! } ! #endif /* NPCI > 0 */ ! } ! ! #ifdef CB_TEST ! static void ! cardbus_print_register(struct slot *slt) ! { ! struct pcic_slot *sp = (struct pcic_slot *)slt->cdata; ! ! if (slt->ctrl->cardbus) { ! int i; ! ! printf ("Cardbus Socket registers:\n"); ! printf("00: "); ! for (i=0;i<16;i+=4) ! printf(" %08x:", cb_getl(sp, i)); ! printf("\n10: "); ! for (i=16;i<32;i+=4) ! printf(" %08x:", cb_getl(sp, i)); ! printf("\n"); ! } } + #endif /* CB_TEST */ /* * pcic_reset - Reset the card and enable initial power. *************** *** 986,1004 **** struct slot *slt = chan; struct pcic_slot *sp = slt->cdata; ! #ifdef PC98 ! if (sp->controller == PCIC_PC98) { ! outb(PCIC98_REG0, 0); ! outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_IOMEMORY)); ! outb(PCIC98_REG3, PCIC98_INTDISABLE); ! outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_VCC3P3V)); ! outb(PCIC98_REG6, inb(PCIC98_REG6) & (~PCIC98_VPP12V)); ! outb(PCIC98_REG1, 0); ! ! selwakeup(&slt->selp); ! return; } ! #endif switch (slt->insert_seq) { case 0: /* Something funny happended on the way to the pub... */ return; --- 1376,1388 ---- struct slot *slt = chan; struct pcic_slot *sp = slt->cdata; ! #ifdef CB_TEST ! if (bootverbose) { ! printf("pcic_reset\n"); ! cardbus_print_register(slt); } ! #endif /* CB_TEST */ ! switch (slt->insert_seq) { case 0: /* Something funny happended on the way to the pub... */ return; *************** *** 1013,1032 **** timeout(pcic_reset, (void *)slt, hz/4); return; case 3: /* Wait if card needs more time */ ! if (!sp->getb(sp, PCIC_STATUS) & PCIC_READY) { timeout(pcic_reset, (void *)slt, hz/10); return; } } slt->insert_seq = 0; - if (sp->controller == PCIC_PD672X || sp->controller == PCIC_PD6710) { - sp->putb(sp, PCIC_TIME_SETUP0, 0x1); - sp->putb(sp, PCIC_TIME_CMD0, 0x6); - sp->putb(sp, PCIC_TIME_RECOV0, 0x0); - sp->putb(sp, PCIC_TIME_SETUP1, 1); - sp->putb(sp, PCIC_TIME_CMD1, 0xf); - sp->putb(sp, PCIC_TIME_RECOV1, 0); - } selwakeup(&slt->selp); } --- 1397,1408 ---- timeout(pcic_reset, (void *)slt, hz/4); return; case 3: /* Wait if card needs more time */ ! if (!getb(sp, PCIC_STATUS) & PCIC_READY) { timeout(pcic_reset, (void *)slt, hz/10); return; } } slt->insert_seq = 0; selwakeup(&slt->selp); } *************** *** 1038,1050 **** { struct pcic_slot *sp = slt->cdata; ! #ifdef PC98 ! if (sp->controller == PCIC_PC98) { ! return; ! } ! #endif ! sp->putb(sp, PCIC_INT_GEN, 0); ! sp->putb(sp, PCIC_POWER, 0); } /* --- 1414,1421 ---- { struct pcic_slot *sp = slt->cdata; ! putb(sp, PCIC_INT_GEN, 0); ! putb(sp, PCIC_POWER, 0); } /* *************** *** 1064,1108 **** * register. If this is non-zero, then a change has occurred * on this card, so send an event to the main code. */ ! static void pcicintr(int unit) { int slot, s; unsigned char chg; struct pcic_slot *sp = pcic_slots; - #ifdef PC98 - if (sp->controller == PCIC_PC98) { - slot = 0; - s = splhigh(); - /* Check for a card in this slot */ - if (inb(PCIC98_REG1) & PCIC98_CARDEXIST) { - if (sp->slt->laststate != filled) { - pccard_event(sp->slt, card_inserted); - } - } else { - if (sp->slt->laststate != empty) { - pccard_event(sp->slt, card_removed); - } - } - splx(s); - return; - } - #endif /* PC98 */ s = splhigh(); ! for (slot = 0; slot < PCIC_MAX_SLOTS; slot++, sp++) ! if (sp->slt && (chg = sp->getb(sp, PCIC_STAT_CHG)) != 0) if (chg & PCIC_CDTCH) { ! if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) == PCIC_CD) { pccard_event(sp->slt, card_inserted); } else { pccard_event(sp->slt, card_removed); } } splx(s); } /* * pcic_resume - Suspend/resume support for PCIC */ --- 1435,1532 ---- * register. If this is non-zero, then a change has occurred * on this card, so send an event to the main code. */ ! void pcicintr(int unit) { int slot, s; unsigned char chg; struct pcic_slot *sp = pcic_slots; s = splhigh(); ! #ifdef PC98 ! if (sp->controller == PCIC_PC98) { ! u_char reg1; ! /* Check for a card in this slot */ ! reg1 = inb(PCIC98_REG1); ! if ((pcic98_last_reg1 ^ reg1) & PCIC98_CARDEXIST) { ! pcic98_last_reg1 = reg1; ! if (reg1 & PCIC98_CARDEXIST) ! pccard_event(sp->slt, card_inserted); ! else ! pccard_event(sp->slt, card_removed); ! } ! } else { ! #endif ! for (slot = 0; slot < PCIC_MAX_SLOTS * NPCIC; slot++, sp++) { ! if (sp->slt && (chg = getb(sp, PCIC_STAT_CHG)) != 0) if (chg & PCIC_CDTCH) { ! #ifdef CB_TEST ! if (bootverbose) { ! printf("pcicintr\n"); ! cardbus_print_register(sp->slt); ! } ! if (sp->slt->ctrl->cardbus) { ! u_long reg; ! ! reg = cb_getl(sp, CB_PRESENT_STATE); ! if (bootverbose) { ! if (reg & CB_16BIT_CARD) ! printf("16bit card\n"); ! if (reg & CB_CB_CARD) ! printf("CardBus card\n"); ! if (reg & CB_5V_CARD) ! printf("5V card\n"); ! if (reg & CB_3V_CARD) ! printf("3V card\n"); ! } ! } ! #endif /* CB_TEST */ ! if ((getb(sp, PCIC_STATUS) & PCIC_CD) == PCIC_CD) { pccard_event(sp->slt, card_inserted); + #ifdef CB_TEST + if (bootverbose) { + printf("inserted\n"); + cardbus_print_register(sp->slt); + } + #endif /* CB_TEST */ } else { pccard_event(sp->slt, card_removed); } } + } + #ifdef PC98 + } + #endif splx(s); } + #ifdef CB_TEST + void + pcic_intr_sc(void *arg) + { + int slot, s; + unsigned char chg; + struct slot_ctrl *cinfo = (struct slot_ctrl *)arg; + struct slot *slt; + struct pcic_slot *sp; + + #if 0 + /* intr slot_list per controller */ + for (slt = cinfo->slot_list; slt; slt = slt->next) { + sp = (struct pcic_slot *)slt->cdata; + pcic_status(slt); + if (status) + pccard_event(slt, card_inserted); + else + pccard_event(slt, card_removed); + } + #else + pcicintr(0); /* XXXX */ + #endif + } + #endif /* CB_TEST */ + /* * pcic_resume - Suspend/resume support for PCIC */ *************** *** 1110,1119 **** pcic_resume(struct slot *slt) { struct pcic_slot *sp = slt->cdata; ! if (pcic_irq > 0) ! sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); ! if (sp->controller == PCIC_PD672X) { ! setb(sp, PCIC_MISC1, PCIC_SPKR_EN); ! setb(sp, PCIC_MISC2, PCIC_LPDM_EN); } } --- 1534,1769 ---- pcic_resume(struct slot *slt) { struct pcic_slot *sp = slt->cdata; ! if (sp->irq > 0) ! putb(sp, PCIC_STAT_INT, (sp->irq << 4) | 0xF); ! } ! ! #ifdef PC98 ! /* ! * local functions for PC98 Original PC-Card controller ! */ ! #define PCIC98_ALWAYS_128MAPPING 1 ! ! static int ! pcic98_memory(struct slot *slt, int win) ! { ! struct mem_desc *mp = &slt->mem[win]; ! unsigned char x; ! ! if (mp->flags & MDF_ACTIVE) { ! /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */ ! if ((unsigned long)mp->start != 0xda000) { ! printf( ! "sys_addr must be 0xda000. requested address = 0x%x\n", ! mp->start); ! return(EINVAL); ! } ! ! /* omajinai ??? */ ! outb(PCIC98_REG0, 0); ! x = inb(PCIC98_REG1); ! x &= 0xfc; ! x |= 0x02; ! outb(PCIC98_REG1, x); ! outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN); ! outw(PCIC98_REG_PAGOFS, (mp->card >> 13)); /* 8KB */ ! ! if (mp->flags & MDF_ATTR) { ! outb(PCIC98_REG6, inb(PCIC98_REG6) | PCIC98_ATTRMEM); ! }else{ ! outb(PCIC98_REG6, inb(PCIC98_REG6) & (~PCIC98_ATTRMEM)); ! } ! ! outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN); ! #if 0 ! if (mp->flags & MDF_16BITS == 1) { /* 16bit */ ! outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_8BIT)); ! }else{ /* 8bit */ ! outb(PCIC98_REG2, inb(PCIC98_REG2) | PCIC98_8BIT); ! } ! #endif ! } else { /* !(mp->flags & MDF_ACTIVE) */ ! outb(PCIC98_REG0, 0); ! x = inb(PCIC98_REG1); ! x &= 0xfc; ! x |= 0x02; ! outb(PCIC98_REG1, x); ! outb(PCIC98_REG_WINSEL, PCIC98_UNMAPWIN); ! outw(PCIC98_REG_PAGOFS, 0); ! } ! return 0; ! } ! ! static int ! pcic98_io(struct slot *slt, int win) ! { ! struct io_desc *ip = &slt->io[win]; ! unsigned char x; ! unsigned short base; ! u_short ofst; ! ! if (win != 0) { ! /* ignore for UE2212 */ ! printf( ! "pcic98:Illegal PCIC I/O window(%d) request! Ignored.\n", win); ! /* return(EINVAL);*/ ! return 0; ! } ! ! if (ip->flags & IODF_ACTIVE) { ! x = inb(PCIC98_REG2) & 0x0f; ! if (! (ip->flags & IODF_CS16)) ! x |= PCIC98_8BIT; ! ! ofst = ip->start & 0xf; ! #ifdef PCIC98_ALWAYS_128MAPPING ! /* trick for using UE2212 */ ! x |= PCIC98_MAP128; ! ofst = ofst + ((ip->start & 0x70) << 4); ! #else ! if (ip->size + ofst > 16) { /* 128bytes mapping */ ! x |= PCIC98_MAP128; ! ofst = ofst + ((ip->start & 0x70) << 4); ! } ! #endif ! ! x |= PCIC98_MAPIO; ! outb(PCIC98_REG2, x); ! ! outw(PCIC98_REG4, PCIC98_IOBASE); /* 98side IO base */ ! outw(PCIC98_REG5, ip->start); /* card side IO base */ ! ! base = PCIC98_IOBASE + ofst; ! ! #ifdef PCIC_DEBUG ! printf("pcic98: " ! "IO mapped 0x%04x(98) -> 0x%04x(Card) and width %d bytes\n", ! base, ip->start, ip->size); ! #endif ! ip->start = base; ! }else{ ! outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_MAPIO)); ! } ! return 0; ! } ! ! static int ! pcic98_power(struct slot *slt) ! { ! unsigned char reg; ! ! reg = inb(PCIC98_REG6) & (~PCIC98_VPP12V); ! switch(slt->pwr.vpp) { ! default: ! return(EINVAL); ! case 50: ! break; ! case 120: ! reg |= PCIC98_VPP12V; ! break; ! } ! outb(PCIC98_REG6, reg); ! DELAY(100*1000); ! ! reg = inb(PCIC98_REG2) & (~PCIC98_VCC3P3V); ! switch(slt->pwr.vcc) { ! default: ! return(EINVAL); ! case 33: ! reg |= PCIC98_VCC3P3V; ! break; ! case 50: ! break; ! } ! outb(PCIC98_REG2, reg); ! DELAY(100*1000); ! return 0; ! } ! ! static void ! pcic98_mapirq(struct slot *slt, int irq) ! { ! u_char x; ! ! switch (irq) { ! case 3: ! x = PCIC98_INT0; ! break; ! case 5: ! x = PCIC98_INT1; ! break; ! case 6: ! x = PCIC98_INT2; ! break; ! case 10: ! x = PCIC98_INT4; ! break; ! case 12: ! x = PCIC98_INT5; ! break; ! case 0: /* disable */ ! x = PCIC98_INTDISABLE; ! break; ! default: ! printf("pcic98: illegal irq %d\n", irq); ! return; ! } ! #ifdef PCIC_DEBUG ! printf("pcic98: irq=%d mapped.\n", irq); ! #endif ! outb(PCIC98_REG3, x); ! } ! ! static void ! pcic98_reset(void *chan) ! { ! struct slot *slt = chan; ! ! outb(PCIC98_REG0, 0); ! outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_MAPIO)); ! outb(PCIC98_REG3, PCIC98_INTDISABLE); ! outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_VCC3P3V)); ! outb(PCIC98_REG6, inb(PCIC98_REG6) & (~PCIC98_VPP12V)); ! outb(PCIC98_REG1, 0); ! ! selwakeup(&slt->selp); ! } ! ! static void ! pcic98_disable(struct slot *slt) ! { ! /* null function */ ! } ! ! static void ! pcic98_resume(struct slot *slt) ! { ! /* XXX PCIC98 How ? */ ! } ! #endif /* PC98 */ ! /* end of local functions for PC98 Original PC-Card controller */ ! ! #ifdef NECMG ! /* ! * local functions for NECMG ! */ ! static void ! necmg_pcic_reset(void *chan) ! { ! struct slot *slt = chan; ! struct pcic_slot *sp = slt->cdata; ! /* ! * Lock out access to wd controler. ! */ ! clrb (sp, PCIC_INT_GEN, PCIC_CARDRESET); ! DELAY(250*1000); ! setb (sp, PCIC_INT_GEN, PCIC_CARDRESET|PCIC_IOCARD); ! DELAY(250*1000); ! while (!getb1(sp, PCIC_STATUS) & PCIC_READY) { ! printf("pcic reset timeout?\n"); ! DELAY(100*1000); } } + /* end of local functions for NECMG */ + #endif /* NECMG */ + #endif /* NPCIC */ Index: PAO/sys/pccard/pcic98reg.h diff -c PAO/sys/pccard/pcic98reg.h:1.1.1.1 PAO/sys/pccard/pcic98reg.h:1.1.1.1.10.1 *** PAO/sys/pccard/pcic98reg.h:1.1.1.1 Thu Dec 11 22:37:56 1997 --- PAO/sys/pccard/pcic98reg.h Sun Dec 6 07:49:41 1998 *************** *** 1,10 **** /* ! pcic98reg.h ! ! PC9801NS/A PCMCIA contorer routine conpatible to PCIC ! Noriyuki Hosobuchi 96.1.20 ! ! */ /*--- I/O port definition */ #define PCIC98_REG0 0x0a8e /* byte */ --- 1,10 ---- /* ! * pcic98reg.h ! * ! * PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L. ! * by Noriyuki Hosobuchi ! * ! */ /*--- I/O port definition */ #define PCIC98_REG0 0x0a8e /* byte */ *************** *** 26,34 **** #define PCIC98_CARDEXIST 0x08 /* 1:exist 0:not exist */ /* PCIC98_REG2 */ ! #define PCIC98_IOMEMORY 0x80 /* 1:IO 0:Memory */ ! #define PCIC98_MAPIO 0x40 /* 0:IO map 1:??? */ ! #define PCIC98_8BIT 0x20 /* bit width 1:8bit 0:16bit */ #define PCIC98_MAP128 0x10 /* IO map size 1:128byte 0:16byte */ #define PCIC98_VCC3P3V 0x02 /* Vcc 1:3.3V 0:5.0V */ --- 26,34 ---- #define PCIC98_CARDEXIST 0x08 /* 1:exist 0:not exist */ /* PCIC98_REG2 */ ! #define PCIC98_MAPIO 0x80 /* 1:IO 0:Memory */ ! #define PCIC98_IOTHROUGH 0x40 /* 0:IO map 1:IO addr-through */ ! #define PCIC98_8BIT 0x20 /* bit width 1:8bit 0:16bit */ #define PCIC98_MAP128 0x10 /* IO map size 1:128byte 0:16byte */ #define PCIC98_VCC3P3V 0x02 /* Vcc 1:3.3V 0:5.0V */ Index: PAO/sys/pccard/pcicvar.h diff -c /dev/null PAO/sys/pccard/pcicvar.h:1.1.6.1 *** /dev/null Fri Dec 25 10:52:08 1998 --- PAO/sys/pccard/pcicvar.h Sun Dec 6 07:49:45 1998 *************** *** 0 **** --- 1,127 ---- + /* + * Copyright (c) 1998 NAKAGAWA, Yoshihisa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: pcicvar.h,v 1.1.6.1 1998/12/05 22:49:45 itojun Exp $ + */ + + #ifndef _PCCARD_PCICVAR_H_ + #define _PCCARD_PCICVAR_H_ + + #define PCIC_IO_WIN 2 + #define PCIC_MEM_WIN 5 + + #ifndef PCIC_MAX_SLOTS + #define PCIC_MAX_SLOTS 4 + #endif + + #define PCIC_I82365 0 /* Intel chip */ + #define PCIC_IBM 1 /* IBM clone */ + #define PCIC_VLSI 2 /* VLSI chip */ + #define PCIC_PD672X 3 /* Cirrus logic 672x */ + #define PCIC_PD6710 4 /* Cirrus logic 6710 */ + #define PCIC_PD6729 5 /* Cirrus logic 6729 */ + #define PCIC_VG468 6 /* Vadem 468 */ + #define PCIC_VG469 7 /* Vadem 469 */ + #define PCIC_RF5C396 8 /* Ricoh RF5C396 */ + #define PCIC_IBM_KING 9 /* IBM KING PCMCIA Controller */ + #define PCIC_PC98 10 /* NEC PC98 PCMCIA Controller */ + #define PCIC_TI1130 11 /* TI PCI1130 CardBus bridge */ + #define PCIC_TI1131 12 /* TI PCI1131 CardBus bridge */ + #define PCIC_PD6832 13 /* Cirrus logic PD6832 CardBus bridge */ + #define PCIC_OZ6730 14 /* O2Micro OZ6730 PC-card bridge */ + #define PCIC_TOSHIBA 15 /* Toshiba CardBus bridge */ + #define PCIC_RL5C465 16 /* Ricoh RL5C465 CardBus bridge */ + #define PCIC_TI1250 17 /* TI PCI1250 CardBus bridge */ + #define PCIC_I82365DF 18 /* Intel chip */ + #define PCIC_RL5C475 19 /* Ricoh RL5C475/476 CardBus bridge */ + #define PCIC_TI1220 20 /* TI PCI1220 CardBus bridge */ + #define PCIC_TI1221 21 /* TI PCI1221 CardBus bridge */ + #define PCIC_RL5C478 22 /* Ricoh RL5C478 CardBus bridge */ + + /* + * Address of the controllers. Each controller can manage + * two PCMCIA slots. Up to 8 slots are supported in total. + * The PCIC controller is accessed via an index port and a + * data port. The index port has the 8 bit address of the + * register accessed via the data port. How I long for + * real memory mapped I/O! + * The top two bits of the index address are used to + * identify the port number, and the lower 6 bits + * select one of the 64 possible data registers. + */ + + #ifndef IO_PCIC1 + #define IO_PCIC1 0x3e0 + #endif + #ifndef IO_PCIC2 + #define IO_PCIC2 0x3e2 + #endif + #ifndef IO_PCIC3 + #define IO_PCIC3 0x3e4 + #endif + + #ifdef PC98 + #ifndef PCIC98_IOBASE + #define PCIC98_IOBASE 0x80d0 + #endif + #endif /*PC98*/ + + #ifndef PCIC_IRQ + #ifdef PC98 + #define PCIC_IRQ 6 + #else + #define PCIC_IRQ 5 + #endif + #endif + + /* + * Per-slot data table. + */ + struct pcic_slot { + int slotnum; /* My slot number */ + int index; /* Index register */ + int data; /* Data register */ + int offset; /* Offset value for index */ + int irq; /* controller irq */ + char controller; /* Device type */ + char revision; /* Device Revision */ + struct slot *slt; /* Back ptr to slot */ + u_char (*getb)(struct pcic_slot *sp, int reg); + void (*putb)(struct pcic_slot *sp, int reg, u_char val); + u_char *regs; /* Pointer to regs in mem */ + }; + + int pcic_probe __P((struct slot_ctrl *cinfo, int iobase, int irq)); + int pcic_attach __P((struct slot_ctrl *cinfo, int flags)); + void pcicintr __P((int unit)); /* XXXX */ + void pcic_intr_sc __P((void *arg)); + + #endif /* !_PCCARD_PCICVAR_H_ */ Index: PAO/sys/pccard/slot.h diff -c PAO/sys/pccard/slot.h:1.1.1.2 PAO/sys/pccard/slot.h:1.1.1.2.6.1 *** PAO/sys/pccard/slot.h:1.1.1.2 Sun Apr 5 07:20:56 1998 --- PAO/sys/pccard/slot.h Sun Dec 6 07:49:46 1998 *************** *** 33,38 **** --- 33,42 ---- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef _PCCARD_SLOT_H + #define _PCCARD_SLOT_H + + /* * Controller data - Specific to each slot controller. */ *************** *** 44,49 **** --- 48,57 ---- /* Map io */ void (*reset) __P((void *)); /* init */ + #ifdef CB_TEST + void (*status) __P((struct slot *)); + /* Get status */ + #endif /* CB_TEST */ void (*disable) __P((struct slot *)); /* Disable slot */ int (*power) __P((struct slot *)); *************** *** 65,71 **** --- 73,84 ---- * The rest is maintained by the mainline PC-CARD code. */ struct slot_ctrl *next; /* Allows linked list of controllers */ + struct slot *slot_list; /* Allows linked list of slots */ int slots; /* Slots available */ + char slot_use; /* Slot use */ + #ifdef CB_TEST + int cardbus; /* CardBus flag */ + #endif /* CB_TEST */ }; /* *************** *** 83,89 **** int attr; /* driver attributes */ unsigned int *imask; /* Interrupt mask ptr */ ! struct pccard_device *next; }; /* --- 96,102 ---- int attr; /* driver attributes */ unsigned int *imask; /* Interrupt mask ptr */ ! struct pccard_device *next; /* really need ?? */ }; /* *************** *** 95,101 **** --- 108,124 ---- */ struct pccard_devinfo { struct pccard_device *drv; + /* compatible old driver */ struct isa_device isahd; /* Device details */ + #if 1 + /* new style */ + int pd_iobase; /* base i/o address */ + u_short pd_irq; /* interrupt request ??? */ + caddr_t pd_maddr; /* physical i/o memory address on bus (if any)*/ + int pd_msize; /* size of i/o memory */ + int pd_unit; /* unit number */ + int pd_flags; /* flags */ + #endif #if 0 void *arg; /* Device argument */ #endif *************** *** 103,108 **** --- 126,132 ---- u_char misc[128]; /* For any random info */ struct slot *slt; /* Back pointer to slot */ + /* really need ?? */ struct pccard_devinfo *next; /* List of drivers */ }; *************** *** 128,133 **** --- 152,158 ---- struct power pwr; /* Power values */ struct slot_ctrl *ctrl; /* Per-controller data */ void *cdata; /* Controller specific data */ + int suspend_power; /* Keep power on suspended state */ int pwr_off_pending;/* Power status of slot */ #ifdef DEVFS void *devfs_token; *************** *** 140,143 **** --- 165,171 ---- struct slot *pccard_alloc_slot(struct slot_ctrl *); void pccard_event(struct slot *, enum card_event); + void pccard_add_controller(struct slot_ctrl *); void pccard_remove_controller(struct slot_ctrl *); + + #endif /* _PCCARD_SLOT_H */ Index: PAO/sys/pci/pci.c diff -c PAO/sys/pci/pci.c:1.1.1.3 PAO/sys/pci/pci.c:1.1.1.3.4.2 *** PAO/sys/pci/pci.c:1.1.1.3 Fri Jul 24 19:26:55 1998 --- PAO/sys/pci/pci.c Wed Dec 23 21:20:55 1998 *************** *** 403,408 **** --- 403,409 ---- u_char reg; u_char pciint; int irq; + u_int classcode; pcici_t tag = pcibus->pb_tag (bus, dev, func); /* *************** *** 415,422 **** ** Announce this device */ ! printf ("%s%d <%s> rev %d", dvp->pd_name, unit, name, ! (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff); /* ** Get the int pin number (pci interrupt number a-d) --- 416,425 ---- ** Announce this device */ ! classcode = (unsigned) pci_conf_read (tag, PCI_CLASS_REG) >> 8; ! printf ("%s%d <%s> rev %d class %x", dvp->pd_name, unit, name, ! (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff, ! classcode); /* ** Get the int pin number (pci interrupt number a-d) *************** *** 1577,1587 **** --- 1580,1593 ---- {0x104B, "Bus Logic"}, {0x104C, "TI"}, {0x1060, "UMC"}, + {0x1066, "Pico Power"}, {0x1080, "Contaq"}, {0x1095, "CMD"}, {0x10b9, "ACER Labs"}, {0x10c8, "NeoMagic"}, {0x1106, "VIA Technologies"}, + {0x1179, "Toshiba"}, + {0x1283, "ITE"}, {0x5333, "S3 Inc."}, {0x8086, "Intel Corporation"}, {0x9004, "Adaptec"}, Index: PAO/sys/pci/pcic_p.c diff -c PAO/sys/pci/pcic_p.c:1.1.1.1 PAO/sys/pci/pcic_p.c:1.1.1.1.6.1 *** PAO/sys/pci/pcic_p.c:1.1.1.1 Sun Apr 5 07:21:23 1998 --- PAO/sys/pci/pcic_p.c Sun Dec 6 07:49:55 1998 *************** *** 32,55 **** #include "pci.h" #if NPCI > 0 #include #include #include #include #include #include ! #include #include #include ! static u_long pcic_pci_count = 0; static char *pcic_pci_probe(pcici_t, pcidi_t); static void pcic_pci_attach(pcici_t, int); ! static void pd6832_legacy_init(pcici_t tag, int unit); ! static struct pci_device pcic_pci_driver = { "pcic", pcic_pci_probe, pcic_pci_attach, --- 32,245 ---- #include "pci.h" #if NPCI > 0 + /* share the PCI code with 2.2-RELENG and 3.0-CURRENT */ + #ifndef FREEBSD22 + #define FREEBSD22 + #endif + #include #include #include + #include + #include #include #include ! ! /* for slot.h */ ! #include ! #include ! #include ! ! #include ! #include ! #include ! ! #ifndef FREEBSD22 ! #include ! #endif /* FREEBSD22 */ #include #include + #ifdef FREEBSD22 + /* enable 3.0-compatible routine for 2.2.x */ + #define PCIFBSD22 + #endif ! /* ! * XXX ! * Do our own re-probe protection until a configuration ! * manager can do it for us. This ensures that we don't ! * reprobe a card already found by the PCI probes. ! */ ! static struct pcic_found ! { ! u_long port; ! char probed; ! } found[] = ! { ! { IO_PCIC1, 0 }, ! { IO_PCIC2, 0 }, ! { IO_PCIC3, 0 } ! }; ! ! static u_long ! get_pci_pcic_addr(void) ! { ! u_long iobase = 0; ! int i; ! ! for (i=0; i < sizeof(found)/sizeof(struct pcic_found); i++) { ! if (!found[i].probed) { ! found[i].probed = 1; ! iobase = found[i].port; ! break; ! } ! } ! return iobase; ! } ! ! struct pci_pcic_info ! { ! u_long port; ! int slots; ! pcici_t tag; ! #ifdef CB_TEST ! struct cb_slot *cb_info; ! #endif /* CB_TEST */ ! struct pci_pcic_info *next; ! }; ! ! static struct pci_pcic_info *info_list = NULL; ! #ifdef CB_TEST ! struct cb_slot cb_slots[MAXSLOT]; ! #endif /* CB_TEST */ ! ! static void ! set_pci_pcic_info(u_long iobase, pcici_t tag, int unit) ! { ! struct pci_pcic_info *info; ! ! for (info = info_list; info; info = info->next) { ! if (info->port == iobase) { ! info->slots++; ! return; ! } ! } ! ! info = malloc(sizeof *info, M_DEVBUF, M_NOWAIT); ! if (info) { ! info->port = iobase; ! info->slots = 1; ! info->tag = tag; ! info->next = info_list; ! #ifdef CB_TEST ! info->cb_info = &cb_slots[unit]; ! #endif /* CB_TEST */ ! info_list = info; ! } ! } ! ! int ! get_pci_pcic_info(u_long iobase, pcici_t *tag) ! { ! struct pci_pcic_info *info; ! ! for (info = info_list; info; info = info->next) { ! if (info->port == iobase) { ! *tag = info->tag; ! return 1; ! } ! } ! return 0; ! } ! ! int ! get_pci_pcic_slots(u_long iobase) ! { ! struct pci_pcic_info *info; ! ! for (info = info_list; info; info = info->next) { ! if (info->port == iobase) { ! return info->slots; ! } ! } ! return 0; ! } ! ! #ifdef CB_TEST ! struct cb_slot * ! get_cb_info(u_long iobase) ! { ! struct pci_pcic_info *info; ! ! for (info = info_list; info; info = info->next) { ! if (info->port == iobase) { ! return info->cb_info; ! } ! } ! return NULL; ! } ! #endif /* CB_TEST */ ! ! #ifdef PCIFBSD22 /* compatibility with FreeBSD 3.0 PCI code */ ! u_long pci_cfgread(pcici_t tag, u_long reg, int bytes); ! void pci_cfgwrite(pcici_t tag, u_long reg, u_long data, int bytes); + u_long + pci_cfgread(pcici_t tag, u_long reg, int bytes) + { + int off; + u_long x; + + off = (reg % 4); + x = pci_conf_read(tag, reg - off); + x >>= (8 * off); + switch (bytes) { + case 1: + x &= 0xffu; + break; + case 2: + x &= 0xffffu; + break; + } + return x; + } + + void + pci_cfgwrite(pcici_t tag, u_long reg, u_long data, int bytes) + { + int off; + u_long x, mask; + + off = (reg % 4); + x = pci_conf_read(tag, reg - off); + switch (bytes) { + case 1: + data &= 0xffu; + mask = 0xffu; + break; + case 2: + data &= 0xffffu; + mask = 0xffffu; + break; + } + data <<= (off * 8); + mask <<= (off * 8); + x &= (~mask); + x |= data; + pci_conf_write(tag, reg - off, x); + } + #endif /* PCIFBSD22 */ + + static u_long pcic_pci_count = 0; static char *pcic_pci_probe(pcici_t, pcidi_t); static void pcic_pci_attach(pcici_t, int); ! #ifdef LKM ! struct pci_device pcic_pci_driver = { ! #else static struct pci_device pcic_pci_driver = { + #endif "pcic", pcic_pci_probe, pcic_pci_attach, *************** *** 57,63 **** --- 247,255 ---- NULL }; + #ifndef LKM DATA_SET(pcidevice_set, pcic_pci_driver); + #endif /* * Return the ID string for the controller if the vendor/product id *************** *** 66,196 **** static char * pcic_pci_probe(pcici_t tag, pcidi_t type) { switch (type) { case PCI_DEVICE_ID_PCIC_CLPD6729: ! return ("Cirrus Logic PD6729/6730 PC-Card Controller"); ! case PCI_DEVICE_ID_PCIC_CLPD6832: ! return ("Cirrus Logic PD6832 CardBus Adapter"); ! case PCI_DEVICE_ID_PCIC_TI1130: ! return ("TI 1130 PCMCIA/CardBus Bridge"); ! case PCI_DEVICE_ID_PCIC_TI1131: ! return ("TI 1131 PCI to PCMCIA/CardBus bridge"); default: break; } return (NULL); } /* ! * General PCI based card dispatch routine. Right now ! * it only understands the CL-PD6832. */ static void ! pcic_pci_attach(pcici_t config_id, int unit) { ! u_long pcic_type; /* The vendor id of the PCI pcic */ ! pcic_type = pci_conf_read(config_id, PCI_ID_REG); ! switch (pcic_type) { ! case PCI_DEVICE_ID_PCIC_CLPD6832: ! pd6832_legacy_init(config_id, unit); ! break; } ! if (bootverbose) { ! int i, j; ! u_char *p; ! u_long *pl; ! ! printf("PCI Config space:\n"); ! for (j = 0; j < 0x98; j += 16) { ! printf("%02x: ", j); ! for (i = 0; i < 16; i += 4) ! printf(" %08x", pci_conf_read(config_id, i+j)); ! printf("\n"); } - p = (u_char *)pmap_mapdev(pci_conf_read(config_id, 0x10), - 0x1000); - pl = (u_long *)p; - printf("Cardbus Socket registers:\n"); - printf("00: "); - for (i = 0; i < 4; i += 1) - printf(" %08x:", pl[i]); - printf("\n10: "); - for (i = 4; i < 8; i += 1) - printf(" %08x:", pl[i]); - printf("\nExCa registers:\n"); - for (i = 0; i < 0x40; i += 16) - printf("%02x: %16D\n", i, p + 0x800 + i, " "); } } /* ! * Set up the CL-PD6832 to look like a ISA based PCMCIA chip (a ! * PD672X). This routine is called once per PCMCIA socket. */ static void ! pd6832_legacy_init(pcici_t tag, int unit) { ! u_long bcr; /* to set interrupts */ ! u_short io_port; /* the io_port to map this slot on */ ! static int num6832 = 0; /* The number of 6832s initialized */ ! /* ! * Some BIOS leave the legacy address uninitialized. This ! * insures that the PD6832 puts itself where the driver will ! * look. We assume that multiple 6832's should be laid out ! * sequentially. We only initialize the first socket's legacy port, ! * the other is a dummy. ! */ ! io_port = PCIC_INDEX_0 + num6832 * CLPD6832_NUM_REGS; ! if (unit == 0) ! pci_conf_write(tag, CLPD6832_LEGACY_16BIT_IOADDR, ! io_port & ~PCI_MAP_IO); /* ! * I think this should be a call to pci_map_port, but that ! * routine won't map regiaters above 0x28, and the register we ! * need to map is 0x44. */ ! io_port = pci_conf_read(tag, CLPD6832_LEGACY_16BIT_IOADDR) ! & ~PCI_MAP_IO; ! /* ! * Configure the first I/O window to contain CLPD6832_NUM_REGS ! * words and deactivate the second by setting the limit lower ! * than the base. */ ! pci_conf_write(tag, CLPD6832_IO_BASE0, io_port | 1); ! pci_conf_write(tag, CLPD6832_IO_LIMIT0, ! (io_port + CLPD6832_NUM_REGS) | 1); ! pci_conf_write(tag, CLPD6832_IO_BASE1, (io_port + 0x20) | 1); ! pci_conf_write(tag, CLPD6832_IO_LIMIT1, io_port | 1 ); /* ! * Set default operating mode (I/O port space) and allocate ! * this socket to the current unit. */ ! pci_conf_write(tag, PCI_COMMAND_STATUS_REG, CLPD6832_COMMAND_DEFAULTS ); ! pci_conf_write(tag, CLPD6832_SOCKET, unit); ! /* ! * Set up the card inserted/card removed interrupts to come ! * through the isa IRQ. */ ! bcr = pci_conf_read(tag, CLPD6832_BRIDGE_CONTROL); ! bcr |= (CLPD6832_BCR_ISA_IRQ|CLPD6832_BCR_MGMT_IRQ_ENA); ! pci_conf_write(tag, CLPD6832_BRIDGE_CONTROL, bcr); ! ! /* After initializing 2 sockets, the chip is fully configured */ ! if (unit == 1) ! num6832++; ! if (bootverbose) ! printf("CardBus: Legacy PC-card 16bit I/O address [0x%x]\n", ! io_port); } #endif /* NPCI > 0 */ --- 258,887 ---- static char * pcic_pci_probe(pcici_t tag, pcidi_t type) { + #ifdef CB_TEST + u_long data, class, subclass; + #endif /* CB_TEST */ + switch (type) { + /* 32bit CardBus bridges */ + case PCI_DEVICE_ID_PCIC_CLPD6832_CARDBUS: + return "Cirrus Logic PD6832 PCI/CardBus Bridge"; + case PCI_DEVICE_ID_PCIC_TI1130_CARDBUS: + return ("TI PCI-1130 PCI-CardBus Bridge"); + case PCI_DEVICE_ID_PCIC_TI1131_CARDBUS: + return ("TI PCI-1131 PCI-CardBus Bridge"); + case PCI_DEVICE_ID_PCIC_TI1220_CARDBUS: + return ("TI PCI-1220 PCI-CardBus Bridge"); + case PCI_DEVICE_ID_PCIC_TI1221_CARDBUS: + return ("TI PCI-1221 PCI-CardBus Bridge"); + case PCI_DEVICE_ID_PCIC_TI1250_CARDBUS: + return ("TI PCI-1250 PCI-CardBus Bridge"); + case PCI_DEVICE_ID_TOSHIBA_TOPIC95_CARDBUS: + return ("Toshiba ToPIC95 PCI-CardBus Bridge"); + case PCI_DEVICE_ID_TOSHIBA_TOPIC97_CARDBUS: + return ("Toshiba ToPIC97 PCI-CardBus Bridge"); + case PCI_DEVICE_ID_RICOH_RL5C465_CARDBUS: + return("Ricoh RL5C465 PCI-CardBus Brige"); + case PCI_DEVICE_ID_RICOH_RL5C475_CARDBUS: + return("Ricoh RL5C475 PCI-CardBus Brige"); + case PCI_DEVICE_ID_RICOH_RL5C476_CARDBUS: + return("Ricoh RL5C476 PCI-CardBus Brige"); + case PCI_DEVICE_ID_RICOH_RL5C478_CARDBUS: + return("Ricoh RL5C478 PCI-CardBus Brige"); + /* 16bit PC-card bridges */ case PCI_DEVICE_ID_PCIC_CLPD6729: ! return "Cirrus Logic PD6729/6730 PC-card Bridge"; ! case PCI_DEVICE_ID_PCIC_OZ6729: ! return "O2micro OZ6729 PC-Card Bridge"; ! case PCI_DEVICE_ID_PCIC_OZ6730: ! return "O2micro OZ6730 PC-Card Bridge"; ! default: + #ifdef CB_TEST + data = pci_conf_read(tag, PCI_CLASS_REG); + class = data & PCI_CLASS_MASK; + subclass = data & PCI_SUBCLASS_MASK; + + if (class == PCI_CLASS_BRIDGE + && subclass == PCI_SUBCLASS_BRIDGE_CARDBUS) { + return("generic PCI/CardBus Brige"); + } + #endif /* CB_TEST */ break; } return (NULL); } + static void pci_legacy_attach(pcici_t tag, pcidi_t id, u_long legacy16); + static void generic_cardbus_attach(pcici_t tag, pcidi_t id, int unit); + static void print_cardbus_registers(pcici_t tag); /* ! * TI1XXX PCI-CardBus Host Adapter specific function code. ! * This function is separated from pcic_pci_attach(). ! * Support Device: TI1130,TI1131,TI1250,TI1220. ! * Test Device: TI1221. ! * Takeshi Shibagaki(shiba@jp.freebsd.org). */ static void ! ti1xxx_pci_init(pcici_t tag, u_long pcic_pci_id, u_int8_t func) { ! u_long syscntl,devcntl,cardcntl; ! char buf[128]; ! int ti113x = (pcic_pci_id == PCI_DEVICE_ID_PCIC_TI1130_CARDBUS) ! || (pcic_pci_id == PCI_DEVICE_ID_PCIC_TI1131_CARDBUS); ! ! syscntl = pci_cfgread(tag, TI113X_PCI_SYSTEM_CONTROL, 4); ! devcntl = pci_cfgread(tag, TI113X_PCI_DEVICE_CONTROL, 1); ! cardcntl = pci_cfgread(tag, TI113X_PCI_CARD_CONTROL, 1); ! ! switch(ti113x){ ! case 0 : ! strcpy(buf, "TI12XX PCI Config Reg: "); ! break; ! case 1 : ! strcpy(buf, "TI113X PCI Config Reg: "); ! /* ! * Defalut card control register setting is PCI interrupt. ! * The method of this code switches PCI INT and ISA IRQ ! * by bit 7 of Bridge Control Register(Offset:0x3e,0x13e). ! * Takeshi Shibagaki(shiba@jp.freebsd.org) ! */ ! if(!func) cardcntl |= TI113X_CARDCNTL_PCI_IRQ_ENA; ! cardcntl |= TI113X_CARDCNTL_PCI_IREQ; ! cardcntl |= TI113X_CARDCNTL_PCI_CSC; ! if(syscntl & TI113X_SYSCNTL_CLKRUN_ENA){ ! if(syscntl & TI113X_SYSCNTL_CLKRUN_SEL) ! strcat(buf, "[clkrun irq 12]"); ! else ! strcat(buf, "[clkrun irq 10]"); ! } ! break; ! } ! if(cardcntl & TI113X_CARDCNTL_RING_ENA) ! strcat(buf, "[ring enable]"); ! if(cardcntl & TI113X_CARDCNTL_SPKR_ENA) ! strcat(buf, "[speaker enable]"); ! if(syscntl & TI113X_SYSCNTL_PWRSAVINGS) ! strcat(buf, "[pwr save]"); ! switch(devcntl & TI113X_DEVCNTL_INTR_MASK){ ! case TI113X_DEVCNTL_INTR_ISA : ! strcat(buf, "[CSC parallel isa irq]"); ! break; ! case TI113X_DEVCNTL_INTR_SERIAL : ! strcat(buf, "[CSC serial isa irq]"); ! break; ! case TI113X_DEVCNTL_INTR_NONE : ! strcat(buf, "[pci only]"); ! break; ! case TI12XX_DEVCNTL_INTR_ALLSERIAL : ! strcat(buf, "[FUNC pci int + CSC serial isa irq]"); ! break; ! } ! #if 0 ! pci_cfgwrite(tag, TI113X_PCI_SYSTEM_CONTROL, syscntl, 4); ! pci_cfgwrite(tag, TI113X_PCI_DEVICE_CONTROL, devcntl, 1); ! #endif /* 0 */ ! pci_cfgwrite(tag, TI113X_PCI_CARD_CONTROL, cardcntl, 1); ! if(ti113x){ ! cardcntl = pci_cfgread(tag, TI113X_PCI_CARD_CONTROL, 1); ! switch(cardcntl & TI113X_CARDCNTL_MASK){ ! case TI113X_FUNC0_VALID : ! if(!func) strcat(buf, "[FUNC pci int]"); ! break; ! case TI113X_FUNC1_VALID : ! if(func) strcat(buf, "[FUNC pci int]"); ! break; ! } ! } ! printf("%s\n",buf); ! } ! /* ! * CLPD683X PCI-CardBus Host Adapter specific function code. ! * This function is separated from pcic_pci_attach(). ! * Support Device: CLPD6832. ! * Takeshi Shibagaki(shiba@jp.freebsd.org). ! */ ! static void ! clpd683x_pci_init(pcici_t tag, u_long pcic_pci_id) ! { ! u_long brgcntl; ! char buf[128]; ! strcpy(buf, "CLPD683X PCI Config Reg: "); ! brgcntl = pci_cfgread(tag, CB_PCI_BRIDGE_CTRL, 2); ! /* ! * CLPD683X management interrupt enable bit is bit 11 in bridge ! * control register(offset 0x3d). ! * When this bit is turned on, card status change interrupt sets ! * on ISA IRQ interrupt. ! * Takeshi Shibagaki(shiba@jp.freebsd.org). ! */ ! brgcntl |= CL6832_BCR_MGMT_INT_ENA; ! pci_cfgwrite(tag, CB_PCI_BRIDGE_CTRL, brgcntl, 2); ! brgcntl = pci_cfgread(tag, CB_PCI_BRIDGE_CTRL, 2); ! switch(brgcntl & CL6832_BCR_MGMT_INT_ENA){ ! case CL6832_BCR_MGMT_INT_ENA : ! strcat(buf, "[CSC isa irq]"); ! break; } + printf("%s\n",buf); + } ! /* ! * RL5C4XX PCI-CardBus Host Adapter specific function code. ! * This function is separated from pcic_pci_attach(). ! * Support Device: RL5C465,RL5C475,RL5C476. ! * Test Device: RL5C478. ! * Takeshi Shibagaki(shiba@jp.freebsd.org). ! */ ! static void ! rl5c4xx_init_setup(pcici_t tag, u_long pcic_pci_id) ! { ! u_long mngcntl; ! char buf[128]; ! int new = (pcic_pci_id == PCI_DEVICE_ID_RICOH_RL5C478_CARDBUS); ! ! strcpy(buf, "RL5C4XX PCI Config Reg: "); ! if(!new){ ! mngcntl = pci_cfgread(tag, 0x91, 1); ! /* ! * This code is made with hacking PCI Config Reg of ! * AL-N2T515J5(RL5C476). ! * When The bit 3 of PCI Config Reg(offset 0x91) turned on, ! * CSC interrupt would set to ISA IRQ. ! * Takeshi Shibagaki(shiba@jp.freebsd.org). ! */ ! mngcntl |= 0x08; ! pci_cfgwrite(tag, 0x91, mngcntl, 1); ! mngcntl = pci_cfgread(tag, 0x91, 1); ! switch(mngcntl & 0x08){ ! case 0x08 : ! strcat(buf, "[CSC isa irq]"); ! break; } } + printf("%s\n",buf); } /* ! * General PCI based card dispatch routine. */ static void ! pcic_pci_attach(pcici_t tag, int unit) { ! int i; ! u_int8_t func; ! u_int8_t bus, slot; ! u_long pcic_pci_id, command, legacy16; ! struct slot_ctrl *cinfo; ! ! bus = (u_int8_t)pci_get_bus(tag); ! slot = (u_int8_t)pci_get_device(tag); ! func = (u_int8_t)pci_get_function(tag); ! if (bootverbose) ! printf("bus = %d, slot = %d, func = %d\n", bus, slot, func); ! ! pcic_pci_id = pci_conf_read(tag, PCI_ID_REG); + /* Init. CardBus/PC-card controllers as 16-bit PC-card controllers */ + + /* Place any per "slot" initialization here */ /* ! * In sys/pci/pcireg.h, PCI_COMMAND_STATUS_REG must be separated ! * PCI_COMMAND_REG(0x04) and PCI_STATUS_REG(0x06). ! * Takeshi Shibagaki(shiba@jp.freebsd.org). */ ! command = pci_cfgread(tag, PCI_COMMAND_STATUS_REG, 4); ! command |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE; ! pci_cfgwrite(tag, PCI_COMMAND_STATUS_REG, command, 4); ! ! switch (pcic_pci_id) { ! /* CardBus Bridges */ ! case PCI_DEVICE_ID_PCIC_TI1130_CARDBUS: ! case PCI_DEVICE_ID_PCIC_TI1131_CARDBUS: ! case PCI_DEVICE_ID_PCIC_TI1220_CARDBUS: ! case PCI_DEVICE_ID_PCIC_TI1221_CARDBUS: ! case PCI_DEVICE_ID_PCIC_TI1250_CARDBUS: ! ti1xxx_pci_init(tag, pcic_pci_id, func); ! generic_cardbus_attach(tag, pcic_pci_id, unit); ! break; ! case PCI_DEVICE_ID_PCIC_CLPD6832_CARDBUS: ! clpd683x_pci_init(tag, pcic_pci_id); ! generic_cardbus_attach(tag, pcic_pci_id, unit); ! break; ! case PCI_DEVICE_ID_TOSHIBA_TOPIC95_CARDBUS: ! case PCI_DEVICE_ID_TOSHIBA_TOPIC97_CARDBUS: ! generic_cardbus_attach(tag, pcic_pci_id, unit); ! break; ! case PCI_DEVICE_ID_RICOH_RL5C465_CARDBUS: ! case PCI_DEVICE_ID_RICOH_RL5C475_CARDBUS: ! case PCI_DEVICE_ID_RICOH_RL5C476_CARDBUS: ! case PCI_DEVICE_ID_RICOH_RL5C478_CARDBUS: ! rl5c4xx_init_setup(tag, pcic_pci_id); ! generic_cardbus_attach(tag, pcic_pci_id, unit); ! break; ! /* Legacy PC-card Bridges */ ! case PCI_DEVICE_ID_PCIC_OZ6729: ! case PCI_DEVICE_ID_PCIC_OZ6730: ! case PCI_DEVICE_ID_PCIC_CLPD6729: ! legacy16 = pci_conf_read(tag, PCI_MAP_REG_START) & ~PCI_MAP_IO; ! /* XXX -- should be initialized more carefully */ ! if (!legacy16) { ! legacy16 = get_pci_pcic_addr(); ! pci_conf_write(tag, PCI_MAP_REG_START, ! legacy16 | PCI_MAP_IO); ! } ! #if 0 ! pci_legacy_attach(tag, pcic_pci_id, legacy16); ! #endif ! set_pci_pcic_info(legacy16, tag, unit); ! break; ! } ! ! #if 0 ! if (func == 0) { ! /* Place any per "chip" initialization here */ ! switch (pcic_pci_id) { ! default: ! break; ! } ! } ! #endif ! ! #if 0 ! /* ! * TODO: ! * use PCI IRQ for CSC */ ! /* XXXX */ ! if(!(pci_map_int(tag, cbintr, (void *)0, NULL))) { ! printf(); ! return; ! } ! #endif ! if (bootverbose) ! print_cardbus_registers(tag); ! ! return; ! } ! ! char ! set_controller_info(pcici_t tag, struct slot_ctrl *cinfo) ! { ! char controller = -1; ! pcidi_t id; ! #ifdef CB_TEST ! u_long data, class, subclass; ! ! data = pci_conf_read(tag, PCI_CLASS_REG); ! class = data & PCI_CLASS_MASK; ! subclass = data & PCI_SUBCLASS_MASK; + if (class == PCI_CLASS_BRIDGE && subclass == PCI_SUBCLASS_BRIDGE_CARDBUS) { + cinfo->cardbus = 1; + } + #endif /* CB_TEST */ + + if (!cinfo) return -1; + + id = pci_conf_read(tag, PCI_ID_REG); + + switch (id) { + /* 32bit CardBus bridges */ + case PCI_DEVICE_ID_PCIC_CLPD6832_CARDBUS: + controller = PCIC_PD6832; + cinfo->name = "Cirrus Logic PD-6832 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_PCIC_TI1130_CARDBUS: + controller = PCIC_TI1130; + cinfo->name = "TI PCI-1130 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_PCIC_TI1131_CARDBUS: + controller = PCIC_TI1131; + cinfo->name = "TI PCI-1131 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_PCIC_TI1220_CARDBUS: + controller = PCIC_TI1220; + cinfo->name = "TI PCI-1220 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_PCIC_TI1221_CARDBUS: + controller = PCIC_TI1221; + cinfo->name = "TI PCI-1221 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_PCIC_TI1250_CARDBUS: + controller = PCIC_TI1250; + cinfo->name = "TI PCI-1250 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_TOSHIBA_TOPIC95_CARDBUS: + controller = PCIC_TOSHIBA; + cinfo->name = "TOSHIBA TOPIC95 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_TOSHIBA_TOPIC97_CARDBUS: + controller = PCIC_TOSHIBA; + cinfo->name = "TOSHIBA TOPIC97 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_RICOH_RL5C465_CARDBUS: + controller = PCIC_RL5C465; + cinfo->name = "Ricoh RL5C465 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_RICOH_RL5C475_CARDBUS: + case PCI_DEVICE_ID_RICOH_RL5C476_CARDBUS: + controller = PCIC_RL5C475; + cinfo->name = "Ricoh RL5C475/476 " + "[CardBus bridge mode]"; + break; + case PCI_DEVICE_ID_RICOH_RL5C478_CARDBUS: + controller = PCIC_RL5C478; + cinfo->name = "Ricoh RL5C478 " + "[CardBus bridge mode]"; + break; + /* 16bit PC-card bridges */ + case PCI_DEVICE_ID_PCIC_CLPD6729: + controller = PCIC_PD6729; + cinfo->name = "Cirrus Logic PD-6729/6730 " + "[i82365 compatible mode]"; + break; + case PCI_DEVICE_ID_PCIC_OZ6729: + case PCI_DEVICE_ID_PCIC_OZ6730: + controller = PCIC_OZ6730; + cinfo->name = "O2micro OZ6729/6730 " + "[i82365 compatible mode]"; + break; + default: + #ifdef CB_TEST + if (cinfo->cardbus) { + cinfo->name = "generic CardBus bridge " + "[CardBus bridge mode]"; + } + #endif /* CB_TEST */ + break; + } + + return controller; + } + + static void + pci_legacy_attach(pcici_t tag, pcidi_t id, u_long legacy16) + { + #if 0 + struct slot_ctrl *cinfo; + + cinfo = malloc(sizeof *cinfo, M_DEVBUF, M_NOWAIT); + if (!cinfo) return NULL; + + /* initialize slot_ctrl *cinfo */ + bzero(cinfo, sizeof *cinfo); + cinfo->cardbus = 0; + + /* XXXX */ + pcic_probe(cinfo, legacy16, PCIC_IRQ); + /* override controller info */ + set_controller_info(tag, cinfo); + + pcic_attach(cinfo); + #endif + + return; + } + + static void + generic_cardbus_attach(pcici_t tag, pcidi_t id, int unit) + { + u_int8_t func; + u_long cb_base; + u_int8_t cb_bus, cb_sub_bus; + u_int8_t cb_irq; + u_int16_t command, brgcntl; + static u_long iobase; /* XXXX */ + + #ifdef CB_TEST + static u_long cb_base_mem = CB_BASE_MEM; + static u_int8_t cb_bus_base = CB_BUS_BASE; + #if 0 + struct slot_ctrl *cinfo; + + cinfo = malloc(sizeof *cinfo, M_DEVBUF, M_NOWAIT); + if (!cinfo) return; + #endif + + /* PCI Command and Status */ + command = pci_cfgread(tag, CB_PCI_COMMAND, 2); + command |= CB_CMD_DEFAULT; + pci_cfgwrite(tag, CB_PCI_COMMAND, command, 2); + + /* PC-Card Socket Status/Control Registers Base Address */ + cb_base = pci_cfgread(tag, CB_PCI_SOCKET_BASE, 4); + if (cb_base == 0) { + cb_base = cb_base_mem; + pci_cfgwrite(tag, CB_PCI_SOCKET_BASE, cb_base, 4); + cb_base_mem += 0x1000; + } + cb_base = (u_long)pmap_mapdev(cb_base, 0x1000); + + /* CardBus Bus Number */ + cb_bus = pci_cfgread(tag, CB_PCI_CB_BUS_NUM, 1); + cb_sub_bus = pci_cfgread(tag, CB_PCI_CB_SUB_BUS_NUM, 1); + if (cb_bus == 0) { + /* XXXX */ + cb_bus = cb_bus_base; + cb_sub_bus = cb_bus_base + 2; + pci_cfgwrite(tag, CB_PCI_CB_BUS_NUM, cb_bus, 1); + pci_cfgwrite(tag, CB_PCI_CB_SUB_BUS_NUM, cb_sub_bus, 1); + cb_bus_base += 3; + } + + /* Interrupt Line */ + cb_irq = pci_cfgread(tag, CB_PCI_INT_LINE, 1); + if (cb_irq > 15) cb_irq = 0; + #if 0 + if (cb_irq == 0) { + /* XXXX test code */ + cb_irq = 10; + pci_cfgwrite(tag, CB_PCI_INT_LINE, cb_irq, 1); + } + #endif + + /* Bridge Control */ + brgcntl = pci_cfgread(tag, CB_PCI_BRIDGE_CTRL, 2); + #if 0 + brgcntl &= ~CB_BCR_CB_RESET; + #endif + if (!cb_irq) brgcntl |= CB_BCR_INT_EXCA; /* XXX */ + pci_cfgwrite(tag, CB_PCI_BRIDGE_CTRL, brgcntl, 2); + #endif /* CB_TEST */ + + #ifndef CB_TEST + #ifndef PCI_INTR_ENA /* ! * This code exists to output ISA IRQ indicated in ExCA register(0x03). ! * The recent PAO needs this 3 lines absolutely. Don't remove!! ! * Takeshi Shibagaki(shiba@jp.freebsd.org). */ ! brgcntl = pci_cfgread(tag, CB_PCI_BRIDGE_CTRL, 2); ! brgcntl |= CB_BCR_INT_EXCA; ! pci_cfgwrite(tag, CB_PCI_BRIDGE_CTRL, brgcntl, 2); ! #else /* PCI_INTR_ENA */ /* ! * To output PCI INT indicated in Interrupt Pin Register(0x3d). ! * When each IRQ is routed to per slot, would be enable. ! * Takeshi Shibagaki(shiba@jp.freebsd.org). */ ! brgcntl = pci_cfgread(tag, CB_PCI_BRIDGE_CTRL, 2); ! brgcntl &= ~CB_BCR_INT_EXCA; ! pci_cfgwrite(tag, CB_PCI_BRIDGE_CTRL, brgcntl, 2); ! #endif /* PCI_INTR_ENA */ ! #endif /* CB_TEST */ ! ! func = (u_int8_t)pci_get_function(tag); ! ! /* 16bit Legacy Mode Base Address */ ! if (func == 0) { ! #if 1 ! u_long legacy16; ! ! legacy16 = pci_cfgread(tag, CB_PCI_LEGACY16_IOADDR, 2) ! & ~PCI_MAP_IO; ! iobase = legacy16; /* XXXX */ ! if (!legacy16) { ! u_int res; ! ! legacy16 = get_pci_pcic_addr(); ! if (!legacy16) { ! printf("not free legacy mode address\n"); ! return; ! } ! iobase = legacy16; /* XXXX */ ! legacy16 |= PCI_MAP_IO; ! pci_cfgwrite(tag, CB_PCI_LEGACY16_IOADDR, legacy16, 2); ! res = pci_cfgread(tag, CB_PCI_LEGACY16_IOADDR, 2) ! & ~PCI_MAP_IO; ! if (bootverbose) ! printf("pcic%d, Legacy PC-card " ! "16bit I/O address is set to 0x%x " ! "(res: 0x%x)\n", ! unit, iobase, res); ! iobase = res; ! } else { ! if (bootverbose) ! printf("pcic%d, Legacy PC-card " ! "16bit I/O address [0x%x]\n", ! unit, iobase); ! } ! } ! #else ! pci_cfgwrite(tag, CB_PCI_LEGACY16_IOADDR, 0, 4); ! #endif ! ! #if 0 ! /* initialize slot_ctrl *cinfo */ ! bzero(cinfo, sizeof *cinfo); ! cinfo->cardbus = 1; ! cinfo->tag = tag; ! ! /* XXXX */ ! pcic_probe(cinfo, cb_base, PCIC_IRQ); ! /* override controller info */ ! set_controller_info(tag, cinfo); ! ! /* attach controller and slot */ ! pcic_attach(cinfo); ! #endif ! ! #ifdef CB_TEST ! /* XXXX */ ! cb_slots[unit].tag = tag; ! cb_slots[unit].cb_base = cb_base; ! cb_slots[unit].cb_bus = cb_bus; ! cb_slots[unit].cb_irq = cb_irq; ! #endif /* CB_TEST */ ! set_pci_pcic_info(iobase, tag, unit); ! ! return; ! } ! ! static void ! print_cardbus_registers(pcici_t tag) ! { ! int i,j; ! u_char *p; ! u_long *pl; ! ! printf ("PCI Config space:\n"); ! for (j=0;j<0x100;j+=16) { ! printf("%02x: ", j); ! for (i=0;i<16;i+=4) { ! printf(" %08x", pci_conf_read(tag, i+j)); ! } ! printf("\n"); ! } ! #ifdef CB_TEST ! /* pci_conf_write(tag, 0x44, 1); */ ! p = (u_char*)pmap_mapdev(pci_conf_read(tag, 0x10), 0x1000); ! pl = (u_long *)p; ! printf ("Cardbus Socket registers:\n"); ! printf("00: "); ! for (i=0;i<4;i+=1) printf(" %08x:",pl[i]); ! printf("\n10: "); ! for (i=4;i<8;i+=1) printf(" %08x:",pl[i]); ! printf ("\nExCa registers:\n"); ! for (i=0;i<0x40;i+=16) ! printf("%02x: %16D\n",i, p+0x800+i," "); ! #endif /* CB_TEST */ } + #endif /* NPCI > 0 */ Index: PAO/sys/pci/pcic_p.h diff -c PAO/sys/pci/pcic_p.h:1.1.1.1 PAO/sys/pci/pcic_p.h:1.1.1.1.6.1 *** PAO/sys/pci/pcic_p.h:1.1.1.1 Sun Apr 5 07:21:23 1998 --- PAO/sys/pci/pcic_p.h Sun Dec 6 07:49:57 1998 *************** *** 29,54 **** * $Id: pcic_p.h,v 1.3.2.1 1998/02/07 20:38:58 nate Exp $ */ ! /* PCI/CardBus Device IDs */ ! #define PCI_DEVICE_ID_PCIC_CLPD6729 0x11001013ul ! #define PCI_DEVICE_ID_PCIC_CLPD6832 0x11101013ul ! #define PCI_DEVICE_ID_PCIC_O2MICRO 0x673A1217ul ! #define PCI_DEVICE_ID_PCIC_TI1130 0xAC12104Cul ! #define PCI_DEVICE_ID_PCIC_TI1131 0xAC15104Cul ! ! /* CL-PD6832 CardBus defines */ ! #define CLPD6832_IO_BASE0 0x002c ! #define CLPD6832_IO_LIMIT0 0x0030 ! #define CLPD6832_IO_BASE1 0x0034 ! #define CLPD6832_IO_LIMIT1 0x0038 ! #define CLPD6832_BRIDGE_CONTROL 0x003c ! #define CLPD6832_LEGACY_16BIT_IOADDR 0x0044 ! #define CLPD6832_SOCKET 0x004c ! ! /* Configuration constants */ ! #define CLPD6832_BCR_MGMT_IRQ_ENA 0x08000000 ! #define CLPD6832_BCR_ISA_IRQ 0x00800000 ! #define CLPD6832_COMMAND_DEFAULTS 0x00000045 ! #define CLPD6832_NUM_REGS 2 ! /* End of CL-PD6832 defines */ --- 29,259 ---- * $Id: pcic_p.h,v 1.3.2.1 1998/02/07 20:38:58 nate Exp $ */ ! #ifndef _PCIC_P_H_ ! #define _PCIC_P_H_ ! #ifdef PCIFBSD22 /* compatibility with FreeBSD 3.0 PCI code */ ! u_long pci_cfgread(pcici_t tag, u_long reg, int bytes); ! void pci_cfgwrite(pcici_t tag, u_long reg, u_long data, int bytes); ! #endif /* PCIFBSD22 */ ! ! /* PCI-PCMCIA Device IDs */ ! #define PCI_DEVICE_ID_PCIC_CLPD6729 0x11001013ul ! #define PCI_DEVICE_ID_PCIC_OZ6729 0x67291217ul ! #define PCI_DEVICE_ID_PCIC_OZ6730 0x673A1217ul ! ! /* PCI-CardBus Device IDs */ ! #define PCI_DEVICE_ID_PCIC_CLPD6832_CARDBUS 0x11101013ul ! #define PCI_DEVICE_ID_PCIC_TI1130_CARDBUS 0xac12104cul ! #define PCI_DEVICE_ID_PCIC_TI1131_CARDBUS 0xac15104cul ! #define PCI_DEVICE_ID_PCIC_TI1220_CARDBUS 0xac17104cul ! #define PCI_DEVICE_ID_PCIC_TI1221_CARDBUS 0xac19104cul /* XXX - test */ ! #define PCI_DEVICE_ID_PCIC_TI1250_CARDBUS 0xac16104cul ! #define PCI_DEVICE_ID_TOSHIBA_TOPIC95_CARDBUS 0x060a1179ul /* XXX - test */ ! #define PCI_DEVICE_ID_TOSHIBA_TOPIC97_CARDBUS 0x060f1179ul /* XXX - test */ ! #define PCI_DEVICE_ID_RICOH_RL5C465_CARDBUS 0x04651180ul ! #define PCI_DEVICE_ID_RICOH_RL5C475_CARDBUS 0x04751180ul ! #define PCI_DEVICE_ID_RICOH_RL5C476_CARDBUS 0x04761180ul ! #define PCI_DEVICE_ID_RICOH_RL5C478_CARDBUS 0x04781180ul /* XXX - test */ ! ! /* PCI Configuration Registers (common) */ ! #define CB_PCI_VENDOR_ID 0x00 /* vendor ID */ ! #define CB_PCI_DEVICE_ID 0x02 /* device ID */ ! #define CB_PCI_COMMAND 0x04 /* PCI command */ ! #define CB_PCI_STATUS 0x06 /* PCI status */ ! #define CB_PCI_REVISION_ID 0x08 /* PCI revision ID */ ! #define CB_PCI_CLASS 0x09 /* PCI class code */ ! #define CB_PCI_CACHE_LINE_SIZE 0x0c /* Cache line size */ ! #define CB_PCI_LATENCY 0x0d /* PCI latency timer */ ! #define CB_PCI_HEADER_TYPE 0x0e /* PCI header type */ ! #define CB_PCI_BIST 0x0f /* Built-in self test */ ! #define CB_PCI_SOCKET_BASE 0x10 /* Socket/ExCA base address reg. */ ! #define CB_PCI_CB_STATUS 0x16 /* CardBus Status */ ! #define CB_PCI_PCI_BUS_NUM 0x18 /* PCI bus number */ ! #define CB_PCI_CB_BUS_NUM 0x19 /* CardBus bus number */ ! #define CB_PCI_CB_SUB_BUS_NUM 0x1A /* Subordinate CardBus bus number */ ! #define CB_PCI_CB_LATENCY 0x1A /* CardBus latency timer */ ! #define CB_PCI_MEMBASE0 0x1C /* Memory base register 0 */ ! #define CB_PCI_MEMLIMIT0 0x20 /* Memory limit register 0 */ ! #define CB_PCI_MEMBASE1 0x24 /* Memory base register 1 */ ! #define CB_PCI_MEMLIMIT1 0x28 /* Memory limit register 1 */ ! #define CB_PCI_IOBASE0 0x2C /* I/O base register 0 */ ! #define CB_PCI_IOLIMIT0 0x30 /* I/O limit register 0 */ ! #define CB_PCI_IOBASE1 0x34 /* I/O base register 1 */ ! #define CB_PCI_IOLIMIT1 0x38 /* I/O limit register 1 */ ! #define CB_PCI_INT_LINE 0x3C /* Interrupt Line */ ! #define CB_PCI_INT_PIN 0x3D /* Interrupt Pin */ ! #define CB_PCI_BRIDGE_CTRL 0x3E /* Bridge Control */ ! #define CB_PCI_SUBSYS_VENDOR_ID 0x40 /* Subsystem Vendor ID */ ! #define CB_PCI_SUBSYS_ID 0x42 /* Subsystem ID */ ! #define CB_PCI_LEGACY16_IOADDR 0x44 /* Legacy 16bit I/O address */ ! ! /* For PCI Command register (CB_PCI_COMMAND) */ ! #define CB_CMD_DEFAULT 0x0007 ! ! /* For Bridge Control register (CB_PCI_BRIDGE_CTRL) */ ! #define CB_BCR_CB_RESET 0x0040 ! #define CB_BCR_INT_EXCA 0x0080 ! ! /* Vendor specific PCI configuration regisrers */ ! ! /* Texas Instruments PCI-1130/1131 CardBus Controller */ ! #define TI113X_PCI_SYSTEM_CONTROL 0x80 /* System Control */ ! #define TI113X_PCI_RETRY_STATUS 0x90 /* Retry Status */ ! #define TI113X_PCI_CARD_CONTROL 0x91 /* Card Control */ ! #define TI113X_PCI_DEVICE_CONTROL 0x92 /* Device Control */ ! #define TI113X_PCI_BUFFER_CONTROL 0x93 /* Buffer Control */ ! #define TI113X_PCI_SOCKET_DMA0 0x94 /* Socket DMA Register 0 */ ! #define TI113X_PCI_SOCKET_DMA1 0x98 /* Socket DMA Register 1 */ ! ! /* Card control register (TI113X_SYSTEM_CONTROL == 0x80) */ ! #define TI113X_SYSCNTL_VCC_PROTECT 0x00200000u ! #define TI113X_SYSCNTL_CLKRUN_SEL 0x00000080u ! #define TI113X_SYSCNTL_PWRSAVINGS 0x00000040u ! #define TI113X_SYSCNTL_KEEP_CLK 0x00000002u ! #define TI113X_SYSCNTL_CLKRUN_ENA 0x00000001u ! ! /* Card control register (TI113X_CARD_CONTROL == 0x91) */ ! #define TI113X_CARDCNTL_RING_ENA 0x80u ! #define TI113X_CARDCNTL_ZOOM_VIDEO 0x40u ! #define TI113X_CARDCNTL_PCI_IRQ_ENA 0x20u ! #define TI113X_CARDCNTL_PCI_IREQ 0x10u ! #define TI113X_CARDCNTL_PCI_CSC 0x08u ! #define TI113X_CARDCNTL_MASK (TI113X_CARDCNTL_PCI_IRQ_ENA | TI113X_CARDCNTL_PCI_IREQ | TI113X_CARDCNTL_PCI_CSC) ! #define TI113X_FUNC0_VALID TI113X_CARDCNTL_MASK ! #define TI113X_FUNC1_VALID (TI113X_CARDCNTL_PCI_IREQ | TI113X_CARDCNTL_PCI_CSC) ! /* Reserved bit 0x04u */ ! #define TI113X_CARDCNTL_SPKR_ENA 0x02u ! #define TI113X_CARDCNTL_INT 0x01u ! ! /* Device control register (TI113X_DEVICE_CONTROL == 0x92) */ ! #define TI113X_DEVCNTL_5V_SOCKET 0x40u ! #define TI113X_DEVCNTL_3V_SOCKET 0x20u ! #define TI113X_DEVCNTL_INTR_MASK 0x06u ! #define TI113X_DEVCNTL_INTR_NONE 0x00u ! #define TI113X_DEVCNTL_INTR_ISA 0x02u ! #define TI113X_DEVCNTL_INTR_SERIAL 0x04u ! /* TI112X specific code */ ! #define TI12XX_DEVCNTL_INTR_ALLSERIAL 0x06u ! ! /* Cirrus Logic PD-6832 CardBus Controller */ ! #define CL6832_PCI_DMA_SLAVE 0x48 /* DMA Slave configuration */ ! #define CL6832_PCI_SOCKET_NUMBER 0x4C /* Socket Number */ ! ! /* bridge control register (CB_PCI_BRIDGE_CTRL) */ ! #define CL6832_BCR_IREQ_INT_ENA 0x0080u /* IREQ-INT Enable */ ! #define CL6832_BCR_MGMT_INT_ENA 0x0800u /* Management Intr Enable */ ! ! /* Vendor specific ExCA registers (for common part, see i82365.h) */ ! ! /* Texas Instruments PCI-1130/1131 CardBus Controller */ ! #define TI113X_ExCA_IO_OFFSET0 0x36 /* Offset of I/O window */ ! #define TI113X_ExCA_IO_OFFSET1 0x38 /* Offset of I/O window */ ! #define TI113X_ExCA_MEM_WINDOW_PAGE 0x3C /* Memory Window Page */ ! ! /* Cirrus Logic PD-6832 CardBus Controller */ ! #define CL6832_ExCA_MISC1 0x16 /* Misc control 1 */ ! #define CL6832_ExCA_FIFO 0x17 /* FIFO control */ ! #define CL6832_ExCA_MISC2 0x1e /* Misc control 2 */ ! #define CL6832_ExCA_CHIP_INFO 0x1f /* Chip information */ ! #define CL6832_ExCA_ATA 0x1f /* ATA Control */ ! #define CL6832_ExCA_EXTEND_INDEX 0x2e /* Extended Index */ ! #define CL6832_ExCA_EXTEND_DATA 0x2f /* Extended Data */ ! ! /* Extended Index (CL6832_ExCA_EXTEND_INDEX == 0x2e) */ ! #define CL6832_ExCA_EXT_EXT1 0x03 /* Extension Control 1 */ ! #define CL6832_ExCA_EXT_GEN_MAP_U0 0x05 /* Gen Map Upper addr 0 */ ! #define CL6832_ExCA_EXT_GEN_MAP_U1 0x06 /* Gen Map Upper addr 1 */ ! #define CL6832_ExCA_EXT_GEN_MAP_U2 0x07 /* Gen Map Upper addr 2 */ ! #define CL6832_ExCA_EXT_GEN_MAP_U3 0x08 /* Gen Map Upper addr 3 */ ! #define CL6832_ExCA_EXT_GEN_MAP_U4 0x09 /* Gen Map Upper addr 4 */ ! #define CL6832_ExCA_EXT_EXT2 0x0b /* Extension Control 2 */ ! #define CL6832_ExCA_EXT_GEN_MAP_U5 0x20 /* Gen Map Upper addr 5 */ ! #define CL6832_ExCA_EXT_GEN_MAP_U6 0x21 /* Gen Map Upper addr 6 */ ! #define CL6832_ExCA_EXT_PCI_SPACE 0x22 /* PCI Space Control */ ! #define CL6832_ExCA_EXT_PCCARD_SPACE 0x23 /* PC-Card Space Control */ ! #define CL6832_ExCA_EXT_WINDOW_TYPE 0x24 /* Window Type Select */ ! #define CL6832_ExCA_EXT_MISC3 0x25 /* Misc Control 3 */ ! #define CL6832_ExCA_EXT_SMB_POWER 0x26 /* SMB Sock Pwr Ctrl Addr */ ! #define CL6832_ExCA_EXT_GEN_MAP_EXTRA0 0x27 /* Gen Map Extra Control 0 */ ! #define CL6832_ExCA_EXT_GEN_MAP_EXTRA1 0x28 /* Gen Map Extra Control 1 */ ! #define CL6832_ExCA_EXT_GEN_MAP_EXTRA2 0x29 /* Gen Map Extra Control 2 */ ! #define CL6832_ExCA_EXT_GEN_MAP_EXTRA3 0x2a /* Gen Map Extra Control 3 */ ! #define CL6832_ExCA_EXT_GEN_MAP_EXTRA4 0x2b /* Gen Map Extra Control 4 */ ! #define CL6832_ExCA_EXT_GEN_MAP_EXTRA5 0x2c /* Gen Map Extra Control 5 */ ! #define CL6832_ExCA_EXT_GEN_MAP_EXTRA6 0x2d /* Gen Map Extra Control 6 */ ! #define CL6832_ExCA_EXT_CSC 0x2e /* Ext. Card Status Change */ ! #define CL6832_ExCA_EXT_MISC4 0x2f /* Misc Control 4 */ ! #define CL6832_ExCA_EXT_MISC5 0x30 /* Misc Control 5 */ ! #define CL6832_ExCA_EXT_MISC6 0x31 /* Misc Control 5 */ ! ! /* infomation about PCI PC-card bridges */ ! ! struct pci_pcic { ! u_int8_t bus; ! u_int8_t slot; ! u_long legacy16; ! u_int pci_id; ! }; ! ! #ifdef CB_TEST ! struct cb_slot { ! /* CardBus support */ ! pcici_t tag; ! u_long cb_base; ! u_int8_t cb_bus; ! u_int8_t cb_irq; ! }; ! ! #ifndef CB_BASE_MEM ! #define CB_BASE_MEM 0x68000000 ! #endif ! #ifndef CB_BUS_BASE ! #define CB_BUS_BASE 0x20 ! #endif ! ! /* ! * CardBus Register index addresses. ! */ ! ! #define CB_STATUS_EVENT 0x00 /* Status Event Register */ ! #define CB_STATUS_MASK 0x04 /* Status Mask Register */ ! #define CB_PRESENT_STATE 0x08 /* Present State Register */ ! #define CB_FORCE 0x0c /* Force Register */ ! #define CB_CONTROL 0x10 /* Control Register */ ! ! /* For Present State and Force register (CB_PRESENT_STATE and CB_FORCE) */ ! #define CB_CSTSCHG 0x00000001u /* Card Status Change */ ! #define CB_CCD1 0x00000002u /* Card Detects 1 */ ! #define CB_CCD2 0x00000004u /* Card Detects 2 */ ! #define CB_POWER_CYCLE 0x00000008u /* Power Cycle */ ! #define CB_16BIT_CARD 0x00000010u /* 16-bit PC Card */ ! #define CB_CB_CARD 0x00000020u /* CardBus PC Card */ ! #define CB_INTERRUPT 0x00000040u /* Interrupt pin from card */ ! #define CB_NOT_A_CARD 0x00000080u /* Not a Card */ ! #define CB_DATA_LOST 0x00000100u /* Data Lost */ ! #define CB_BAD_VCC_REQ 0x00000200u /* Bad Vcc Request */ ! #define CB_5V_CARD 0x00000400u /* 5V Card */ ! #define CB_3V_CARD 0x00000800u /* 3V Card */ ! #define CB_XV_CARD 0x00001000u /* XV Card */ ! #define CB_YV_CARD 0x00002000u /* YV Card */ ! #define CB_CV_TEST 0x00004000u /* test VS and CCD */ ! #define CB_5V_AVAIL 0x10000000u /* 5V Vcc Voltage Available */ ! #define CB_3V_AVAIL 0x20000000u /* 3V Vcc Voltage Available */ ! #define CB_XV_AVAIL 0x40000000u /* XV Vcc Voltage Available */ ! #define CB_YV_AVAIL 0x80000000u /* YV Vcc Voltage Available */ ! ! /* For Control register (CB_CONTROL) */ ! #define CB_VPP_CTRL 0x0007u /* Vpp control bits */ ! #define CB_VPP_0V 0x0000u /* 0 volts */ ! #define CB_VPP_12V 0x0001u /* 12 volts */ ! #define CB_VPP_5V 0x0002u /* 5 volts */ ! #define CB_VPP_3V 0x0003u /* 3 volts */ ! #define CB_VCC_CTRL 0x0070u /* Vcc control bits */ ! #define CB_VCC_0V 0x0000u /* 0 volts */ ! #define CB_VCC_5V 0x0020u /* 5 volts */ ! #define CB_VCC_3V 0x0030u /* 3 volts */ ! #define CB_STOP_CLOCK 0x0080u /* stop CardBus clock */ ! #endif /* CB_TEST */ ! ! #endif /* _PCIC_P_H_ */ Index: PAO/sys/pci/pcireg.h diff -c PAO/sys/pci/pcireg.h:1.1.1.1 PAO/sys/pci/pcireg.h:1.1.1.1.10.1 *** PAO/sys/pci/pcireg.h:1.1.1.1 Thu Dec 11 22:37:59 1997 --- PAO/sys/pci/pcireg.h Sun Dec 6 07:50:00 1998 *************** *** 126,131 **** --- 126,132 ---- #define PCI_SUBCLASS_BRIDGE_MC 0x00030000 #define PCI_SUBCLASS_BRIDGE_PCI 0x00040000 #define PCI_SUBCLASS_BRIDGE_PCMCIA 0x00050000 + #define PCI_SUBCLASS_BRIDGE_CARDBUS 0x00070000 #define PCI_SUBCLASS_BRIDGE_MISC 0x00800000 /* Index: PAO/sys/pci/pcisupport.c diff -c PAO/sys/pci/pcisupport.c:1.1.1.3 PAO/sys/pci/pcisupport.c:1.1.1.3.4.3 *** PAO/sys/pci/pcisupport.c:1.1.1.3 Fri Jul 24 19:27:03 1998 --- PAO/sys/pci/pcisupport.c Wed Dec 23 22:34:29 1998 *************** *** 174,183 **** --- 174,215 ---- return ("Intel 82454GX (Orion) host to PCI bridge"); case 0x00051166: return ("Ross (?) host to PCI bridge"); + case 0xc5571045: + return ("Opti 82C557 (Viper-M) host to PCI bridge"); + case 0xc5581045: + return ("Opti 82C558 (Viper-M) ISA+IDE"); + case 0xc7001045: + return ("Opti 82C700 (FireStar) PCI-ISA bridge"); + case 0xc7011045: + return ("Opti 82C701 (FireStar) host to PCI bridge"); + case 0xd7211045: + return ("Opti (FireStar) IDE interface"); case 0x00221014: return ("IBM 82351 PCI-PCI bridge"); case 0x00011011: return ("DEC 21050 PCI-PCI bridge"); + case 0xe8911060: + return ("UMC UM8891N host to PCI bridge"); + case 0xe8861060: + return ("UMC UM8886N PCI-ISA bridge"); + case 0x673a1060: + return ("UMC UM8886BF PCI Dual IDE controller"); + case 0x83301283: + return ("ITE8330g PCI bridge"); + case 0xe8861283: + return ("ITE8330g PCI-ISA bridge"); + case 0x673a1283: + return ("ITE8330g IDE interface"); + case 0x12341283: + return ("ITE8330g USB interface"); + case 0x00011066: + return ("PicoPower Vesuvius host to PCI bridge"); + case 0x00021066: + return ("PicoPower Vesuvius PCI-ISA bridge"); + case 0x06431095: + return ("CMD 0643 Bus Master PCI-IDE controller"); + case 0x06011179: + return ("TOSHIBA 0601 host to PCI bridge"); /* NEC -- vendor 0x1033 */ case 0x00011033: *************** *** 725,730 **** --- 757,781 ---- pciroots++; } + #ifdef FORCE_IRQ_ROUTING + static void + viper_irq_routing(pcici_t tag) + { + pci_conf_write (tag, 0x40, 0x0008001bul); + } + + static void + piix_irq_routing(pcici_t tag) + { + int elcr2; + /* pci_conf_write (tag, 0x60, 0x0980800aul); */ + pci_conf_write (tag, 0x60, 0x09800a09ul); + elcr2 = inb(0x4d1); + outb(0x4d1, elcr2|0x04); + printf("ELCR2 %02x -> %02x\n", elcr2, elcr2|0x04); + } + #endif /* FORCE_IRQ_ROUTING */ + static void chipset_attach (pcici_t config_id, int unit) { *************** *** 740,745 **** --- 791,810 ---- config_Ross (config_id); break; } + #ifdef FORCE_IRQ_ROUTING + switch (pci_conf_read (config_id, PCI_ID_REG)) { + + case 0xc5581045: /* Opti Viper-M ISA+IDE */ + viper_irq_routing(config_id); + break; + case 0x122e8086: /* Intel PIIX */ + case 0x12348086: /* Intel MPIIX */ + case 0x70008086: /* Intel PIIX3 */ + case 0x71108086: /* Intel PIIX4 */ + piix_irq_routing(config_id); + break; + } + #endif /* FORCE_IRQ_ROUTING */ #ifndef PCI_QUIET if (!bootverbose) return; *************** *** 765,774 **** --- 830,841 ---- break; case 0x70008086: case 0x122e8086: + case 0x71108086: writeconfig (config_id, conf82371fb); break; case 0x70108086: case 0x12308086: + case 0x71118086: writeconfig (config_id, conf82371fb2); break; #if 0 Index: PAO/sys/scsi/scsiconf.c diff -c PAO/sys/scsi/scsiconf.c:1.1.1.2 PAO/sys/scsi/scsiconf.c:1.1.1.2.6.1 *** PAO/sys/scsi/scsiconf.c:1.1.1.2 Sun Apr 5 07:21:45 1998 --- PAO/sys/scsi/scsiconf.c Sun Dec 6 07:50:12 1998 *************** *** 27,33 **** #include #include #include ! #ifdef PC98 #include #endif --- 27,33 ---- #include #include #include ! #if 1 /* PC98 */ #include #endif *************** *** 52,57 **** --- 52,61 ---- static void extend_release __P((struct extend_array *ea, int index)); static void *extend_set __P((struct extend_array *ea, int index, void *value)); + #ifdef SCSI_DETACH + #define UNIT_ALLOC_COUNT 32 + #endif + /* * XXX SCSI_DEVICE_ENTRIES() generates extern switches but it should * generate static switches except for this. Separate macros are *************** *** 250,256 **** { #if NOD > 0 { ! T_OPTICAL, T_OPTICAL, T_REMOV, "MATSHITA", "PD-1 LF-100*", "*", "od", SC_MORE_LUS }, { --- 254,260 ---- { #if NOD > 0 { ! T_OPTICAL, T_OPTICAL, T_REMOV, "MATSHITA", "PD-1 LF-1*", "*", "od", SC_MORE_LUS }, { *************** *** 645,654 **** --- 649,666 ---- * a wired down device, but we do want "sd 4 target 5" or * even "sd 4 scbus 1" to match. */ + #ifdef SCSI_DETACH + if (IS_SPECIFIED(sdc->unit) && + (IS_SPECIFIED(sdc->target) || IS_SPECIFIED(sdc->cunit ))) { + for(i = 0; i <= sdc->unit; i++) + scsi_unit_use(sd, i); + } + #else if (IS_SPECIFIED(sdc->unit) && (IS_SPECIFIED(sdc->target) || IS_SPECIFIED(sdc->cunit)) && sd->free_unit <= sdc->unit) sd->free_unit = sdc->unit + 1; + #endif } } } *************** *** 720,726 **** { int i; int found; ! #ifdef PC98 struct cfdata cf; cf.cf_flags = 0; #endif --- 732,738 ---- { int i; int found; ! #if 1 /* PC98 */ struct cfdata cf; cf.cf_flags = 0; #endif *************** *** 736,742 **** sc_link->scsibus == scsi_dinit[i].cunit) { sc_link->dev_unit = scsi_dinit[i].unit; found = 1; ! #ifdef PC98 cf.cf_flags = scsi_dinit[i].flags; #endif if (bootverbose) --- 748,754 ---- sc_link->scsibus == scsi_dinit[i].cunit) { sc_link->dev_unit = scsi_dinit[i].unit; found = 1; ! #if 1 /* PC98 */ cf.cf_flags = scsi_dinit[i].flags; #endif if (bootverbose) *************** *** 746,755 **** } } ! if (!found) sc_link->dev_unit = sc_link->device->free_unit++; ! #ifdef PC98 if (!found) { for (i = 0; scsi_dinit[i].name; i++) { if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) && --- 758,774 ---- } } ! if (!found) { ! #ifdef SCSI_DETACH ! sc_link->dev_unit = ! scsi_free_unit_get(sc_link->device); ! scsi_unit_use(sc_link->device, sc_link->dev_unit); ! #else sc_link->dev_unit = sc_link->device->free_unit++; + #endif + } ! #if 1 /* PC98 */ if (!found) { for (i = 0; scsi_dinit[i].name; i++) { if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) && *************** *** 1472,1474 **** --- 1491,1603 ---- } return (bestmatch); } + + #ifdef SCSI_DETACH + void + scsi_unit_use(struct scsi_device *device, int unit) + { + int n, i; + u_char mask; + u_char *q; + + if (device->free_unit == 0 || unit >= UNIT_ALLOC_COUNT ) { + if (device->free_unit == 0) + device->max_unit_count = UNIT_ALLOC_COUNT; + n = device->max_unit_count * sizeof(char); + q = malloc(n, M_DEVBUF, M_NOWAIT); + bzero(q, n); + if (device->free_unit) { + bcopy(device->free_unit, q, + n - (UNIT_ALLOC_COUNT * sizeof(char))); + free(device->free_unit,M_DEVBUF); + } + device->free_unit = q; + device->max_unit_count =+ UNIT_ALLOC_COUNT; + } + i = unit / (sizeof(char) * 8); + mask = 1 << (unit - (i * sizeof(char) * 8)); + (device->free_unit)[i] = (device->free_unit)[i] | mask; + #ifdef PCCARD_LKM_DEBUG + printf("unit_use:free_unit=%x mask=%x unit=%d\n", + (device->free_unit)[i], mask, unit); + #endif + } + + void + scsi_unit_unuse(struct scsi_device *device, int unit) + { + int i; + u_char mask; + + i = unit / (sizeof(char) * 8); + mask = 1 << (unit - (i * sizeof(char) * 8)); + #ifdef PCCARD_LKM_DEBUG + printf("unit_unuse:free_unit=%x i=%d\n",(device->free_unit)[i],i); + #endif + (device->free_unit)[i] = (device->free_unit)[i] & ~mask; + #ifdef PCCARD_LKM_DEBUG + printf("unit_unuse:free_unit=%x mask=%x unit=%d\n", + (device->free_unit)[i],~mask,unit); + #endif + } + + int + scsi_free_unit_get(struct scsi_device *device) + { + int i, j, n; + u_char mask; + + if (device->free_unit == 0) { + device->max_unit_count = UNIT_ALLOC_COUNT; + n = device->max_unit_count * sizeof(char); + device->free_unit = malloc(n,M_DEVBUF,M_NOWAIT); + bzero(device->free_unit,n); + } + #ifdef PCCARD_LKM_DEBUG + printf("scsi:unit_get free_unit = %x\n",device->free_unit); + #endif + for(i = 0; i <= (device->max_unit_count / (sizeof(char) * 8)); i++) { + for(j = 0; j < 8; j++) { + mask = 1 << j; + #ifdef PCCARD_LKM_DEBUG + printf("unit_get:mask=%x free_unit=%x\n", + mask,(device->free_unit)[i]); + #endif + if(mask & (device->free_unit)[i]) + continue; + else + return(i * sizeof(char) * 8 + j); + } + } + return(i * sizeof(char) * 8); + } + + void + scsi_detachdev(struct scsibus_data *scbus) + { + struct scsi_link *sc_link; + int targ,lun,i; + + for(targ = 0; targ < scbus->maxtarg + 1; targ++) { + for(lun=0; lun < 8; lun++) { + sc_link = (*scbus->sc_link)[targ][lun]; + if (sc_link) { + scsi_unit_unuse(sc_link->device, + sc_link->dev_unit); + extend_release(scbusses,sc_link->scsibus); + scsi_free_unit(sc_link); + } + } + } + free(scbus->sc_link, M_TEMP); + scbus->sc_link = NULL; + free(scbus,M_TEMP); + scbus = NULL; + } + + struct scsibus_data * + scsi_extend_get(int bus) + { + return (struct scsibus_data *)extend_get(scbusses, bus); + } + #endif /* SCSI_DETACH */ Index: PAO/sys/scsi/scsiconf.h diff -c PAO/sys/scsi/scsiconf.h:1.1.1.2 PAO/sys/scsi/scsiconf.h:1.1.1.2.6.1 *** PAO/sys/scsi/scsiconf.h:1.1.1.2 Sun Apr 5 07:21:46 1998 --- PAO/sys/scsi/scsiconf.h Sun Dec 6 07:50:14 1998 *************** *** 56,62 **** struct buf; struct scsi_xfer; ! #ifdef PC98 struct cfdata; #endif --- 56,62 ---- struct buf; struct scsi_xfer; ! #if 1 /* PC98 */ struct cfdata; #endif *************** *** 77,83 **** { /* 04*/ int32_t (*scsi_cmd) __P((struct scsi_xfer *xs)); /* 08*/ void (*scsi_minphys) __P((struct buf *bp)); ! #ifdef PC98 /* 12*/ int32_t (*open_target_lu) __P((struct scsi_link *sc_link, struct cfdata *cf)); #else --- 77,83 ---- { /* 04*/ int32_t (*scsi_cmd) __P((struct scsi_xfer *xs)); /* 08*/ void (*scsi_minphys) __P((struct buf *bp)); ! #if 1 /* PC98 */ /* 12*/ int32_t (*open_target_lu) __P((struct scsi_link *sc_link, struct cfdata *cf)); #else *************** *** 170,177 **** --- 170,184 ---- /* 80*/ struct extend_array *links; + #ifdef SCSI_DETACH + /* 84*/ u_char *free_unit; + #else /* 84*/ int free_unit; + #endif /* 88*/ struct scsi_device *next; /* Next in list in the registry. */ + #ifdef SCSI_DETACH + int max_unit_count; + #endif }; /* SCSI_DEVICE_ENTRIES: A macro to generate all the entry points from the *************** *** 486,491 **** --- 493,506 ---- errval scsi_change_def( struct scsi_link *sc_link, u_int32_t flags); #endif #endif /* KERNEL */ + + #ifdef SCSI_DETACH + void scsi_unit_use __P((struct scsi_device *, int)); + void scsi_unit_unuse __P((struct scsi_device *, int)); + int scsi_free_unit_get __P((struct scsi_device *)); + struct scsibus_data *scsi_extend_get(int); + void scsi_detachdev __P((struct scsibus_data *)); + #endif #define SCSI_EXTERNALLEN (sizeof(struct scsi_link)) Index: PAO/sys/sys/systm.h diff -c PAO/sys/sys/systm.h:1.1.1.2 PAO/sys/sys/systm.h:1.1.1.2.4.2 *** PAO/sys/sys/systm.h:1.1.1.2 Fri Jul 24 19:28:30 1998 --- PAO/sys/sys/systm.h Tue Dec 22 17:28:04 1998 *************** *** 173,178 **** --- 173,179 ---- int rm_at_shutdown(bootlist_fn function, void *arg); #define SHUTDOWN_PRE_SYNC 0 #define SHUTDOWN_POST_SYNC 1 + #define SHUTDOWN_POWER_OFF 2 /* forking */ /* XXX not yet */ typedef void (*forklist_fn)(struct proc *parent,struct proc *child,int flags);